From d008186824c24400e212c2909476d3c3899ee1cf Mon Sep 17 00:00:00 2001 From: robertl Date: Tue, 2 Dec 2003 15:03:21 +0000 Subject: [PATCH] This commit was generated by cvs2svn to compensate for changes in r564, which included commits to RCS files with non-trunk default branches. --- st2gpx/istorage/istorage LICENCE.txt | 24 + st2gpx/istorage/istorage-make LICENCE.txt | 24 + st2gpx/istorage/istorage-make README.txt | 17 + st2gpx/istorage/istorage-make.cpp | 218 ++ st2gpx/libexpat.dll | Bin 0 -> 143360 bytes st2gpx/src/Expat license.txt | 22 + st2gpx/src/ToDo.txt | 29 + st2gpx/src/annotations.c | 419 +++ st2gpx/src/annotations.h | 181 ++ st2gpx/src/bugs.txt | 21 + st2gpx/src/build.txt | 20 + st2gpx/src/contents.c | 554 ++++ st2gpx/src/contents.h | 224 ++ st2gpx/src/debug.c | 589 ++++ st2gpx/src/gpx.h | 109 + st2gpx/src/history.txt | 31 + st2gpx/src/istorage license.txt | 24 + st2gpx/src/istorage-make license.txt | 24 + st2gpx/src/journey.c | 464 ++++ st2gpx/src/journey.h | 382 +++ st2gpx/src/msado15.tlh | 2997 +++++++++++++++++++++ st2gpx/src/msado15.tli | 2095 ++++++++++++++ st2gpx/src/nannol.c | 206 ++ st2gpx/src/ppinutil.c | 290 ++ st2gpx/src/ppinutil.h | 128 + st2gpx/src/properties.c | 452 ++++ st2gpx/src/properties.h | 72 + st2gpx/src/pushpins.cpp | 585 +++- st2gpx/src/pushpins.h | 73 +- st2gpx/src/readgpx.c | 656 +++++ st2gpx/src/readmpst.c | 400 +++ st2gpx/src/st2gpx license.txt | 23 + st2gpx/src/st2gpx.c | 1694 +++--------- st2gpx/src/st2gpx.dsp | 119 +- st2gpx/src/st2gpx.dsw | 12 - st2gpx/src/st2gpx.h | 142 + st2gpx/src/writegpx.c | 317 +++ st2gpx/src/writepcx.c | 469 ++++ 38 files changed, 12625 insertions(+), 1481 deletions(-) create mode 100644 st2gpx/istorage/istorage LICENCE.txt create mode 100644 st2gpx/istorage/istorage-make LICENCE.txt create mode 100644 st2gpx/istorage/istorage-make README.txt create mode 100644 st2gpx/istorage/istorage-make.cpp create mode 100644 st2gpx/libexpat.dll create mode 100644 st2gpx/src/Expat license.txt create mode 100644 st2gpx/src/ToDo.txt create mode 100644 st2gpx/src/annotations.c create mode 100644 st2gpx/src/annotations.h create mode 100644 st2gpx/src/bugs.txt create mode 100644 st2gpx/src/build.txt create mode 100644 st2gpx/src/contents.c create mode 100644 st2gpx/src/contents.h create mode 100644 st2gpx/src/debug.c create mode 100644 st2gpx/src/gpx.h create mode 100644 st2gpx/src/history.txt create mode 100644 st2gpx/src/istorage license.txt create mode 100644 st2gpx/src/istorage-make license.txt create mode 100644 st2gpx/src/journey.c create mode 100644 st2gpx/src/journey.h create mode 100644 st2gpx/src/msado15.tlh create mode 100644 st2gpx/src/msado15.tli create mode 100644 st2gpx/src/nannol.c create mode 100644 st2gpx/src/ppinutil.c create mode 100644 st2gpx/src/ppinutil.h create mode 100644 st2gpx/src/properties.c create mode 100644 st2gpx/src/properties.h create mode 100644 st2gpx/src/readgpx.c create mode 100644 st2gpx/src/readmpst.c create mode 100644 st2gpx/src/st2gpx license.txt create mode 100644 st2gpx/src/st2gpx.h create mode 100644 st2gpx/src/writegpx.c create mode 100644 st2gpx/src/writepcx.c diff --git a/st2gpx/istorage/istorage LICENCE.txt b/st2gpx/istorage/istorage LICENCE.txt new file mode 100644 index 000000000..fde84dffe --- /dev/null +++ b/st2gpx/istorage/istorage LICENCE.txt @@ -0,0 +1,24 @@ +Copyright (c) 2001, Pabs (pabs3@zip.to) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/st2gpx/istorage/istorage-make LICENCE.txt b/st2gpx/istorage/istorage-make LICENCE.txt new file mode 100644 index 000000000..5ee1421bf --- /dev/null +++ b/st2gpx/istorage/istorage-make LICENCE.txt @@ -0,0 +1,24 @@ +Copyright (c) 2002, Pabs (pabs3@zip.to) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/st2gpx/istorage/istorage-make README.txt b/st2gpx/istorage/istorage-make README.txt new file mode 100644 index 000000000..fc0813efc --- /dev/null +++ b/st2gpx/istorage/istorage-make README.txt @@ -0,0 +1,17 @@ +There are two executables, with just the default output type changed: + +istorage-make.exe + defaults to making OLE IStorages + made from the distributed source with MSVC 6 + +its-make.exe + defaults to making compressed ITS ITStorages + made from modified source with MSVC 6 + +Read LICENCE.txt for conditions of distribution and modification. +To use just drag a folder onto the appropriate executable/shortcut. +Don't worry about the warnings saying that the times could not be set. + +Enjoy say i, +Pabs +http://zip.to/pabs3/ \ No newline at end of file diff --git a/st2gpx/istorage/istorage-make.cpp b/st2gpx/istorage/istorage-make.cpp new file mode 100644 index 000000000..6e5cc628d --- /dev/null +++ b/st2gpx/istorage/istorage-make.cpp @@ -0,0 +1,218 @@ +/*Copyright by Pabs (pabs3@zip.to, http://zip.to/pabs3/) Dec 2002*/ + +/*Licenced under the BSD sloppyright - nasty little daemons better not use this source & not attribute me*/ + +/*Compile notes: + M$VC: just open this file & press the build button or select build from the + build menu since this will create a default project that does nicely + GCC/Cygwin: gcc -mno-cygwin -fvtable-thunks -o istorage-make.exe istorage-make.cpp -lole32 should do the trick + if w32api & mingw are set up correctly & the headers are correct + GCC/Wine: You'll have to figure it out for yourself since I don't yet have + access to Linux (Debian) cause I need a new HD + a DVD drive ;-) +*/ + +/* Usage: + -ole + convert to an OLE compound file (default) + -its + convert to an ITS file + -its -uc + don't compress (default) + -its -cd + compress the data after creation + -its -cdp + compress the data and path after creation +*/ + +/*TODO: + think up a proper name + Add popt/getopt processing + use libOLE on non-win32 - http://chicago.sf.net + Implement options for the following + rename specific files to something the normal filesystem can't handle, like 0x1 characters + various tar/unzip options + --help --version +*/ + + +#include +#include +#include +#include + + +//These next few bits are from a sample available from http://www.keyworks.net/code.htm (see http://helpware.net/delphi/index.html for a Delphi sample - need to join a yahoo group first - example 10 is the one to look at) +//This stuff is supposed to be documented in the MSDN, but I only found 1 page that references ITStorage & that is an error codes list +DEFINE_GUID(CLSID_ITStorage, 0x5d02926a, 0x212e, 0x11d0, 0x9d, 0xf9, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec); +DEFINE_GUID(IID_ITStorage, 0x88cc31de, 0x27ab, 0x11d0, 0x9d, 0xf9, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec); + +const GUID CLSID_ITStorage = { 0x5d02926a, 0x212e, 0x11d0, { 0x9d, 0xf9, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec } }; +const GUID IID_ITStorage = { 0x88cc31de, 0x27ab, 0x11d0, { 0x9d, 0xf9, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec} }; + +typedef struct _ITS_Control_Data +{ + UINT cdwControlData; // Number of DWords to follow. + UINT adwControlData[1]; // Actually this will be adwControlData[cdwControlData] +} ITS_Control_Data, *PITS_Control_Data; + +typedef enum ECompactionLev { + COMPACT_DATA = 0, + COMPACT_DATA_AND_PATH +}; + +DECLARE_INTERFACE_(IITStorage, IUnknown) +{ + STDMETHOD(StgCreateDocfile) (const WCHAR* pwcsName, DWORD grfMode, DWORD reserved, IStorage** ppstgOpen) PURE; + STDMETHOD(StgCreateDocfileOnILockBytes) (ILockBytes * plkbyt, DWORD grfMode, DWORD reserved, IStorage** ppstgOpen) PURE; + STDMETHOD(StgIsStorageFile) (const WCHAR * pwcsName) PURE; + STDMETHOD(StgIsStorageILockBytes) (ILockBytes * plkbyt) PURE; + STDMETHOD(StgOpenStorage)(const WCHAR * pwcsName, IStorage * pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage ** ppstgOpen) PURE; + STDMETHOD(StgOpenStorageOnILockBytes)(ILockBytes * plkbyt, IStorage * pStgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage ** ppstgOpen) PURE; + STDMETHOD(StgSetTimes)(WCHAR const* lpszName, FILETIME const* pctime, FILETIME const* patime, FILETIME const* pmtime) PURE; + STDMETHOD(SetControlData)(PITS_Control_Data pControlData) PURE; + STDMETHOD(DefaultControlData)(PITS_Control_Data *ppControlData) PURE; + STDMETHOD(Compact)(const WCHAR* pwcsName, ECompactionLev iLev) PURE; +}; + +IITStorage* ITStorage = NULL; + +struct OPTIONS{ + bool its; + bool compress; + ECompactionLev compression; + char indentchar; + char* ole_appendstring; + char* its_appendstring; +} options = {false,false,COMPACT_DATA,'\t',".ole",".its"}; + +HRESULT r; + +void EnumFolder(char*f,IStorage* is); + +int main(int argc, char *argv[]){ + //Get an instance of the thing to call for creating chms + CoInitialize(NULL); + CoCreateInstance(CLSID_ITStorage, NULL, CLSCTX_INPROC_SERVER, IID_ITStorage, (void**)&ITStorage); + char t[2];DWORD cdl = GetCurrentDirectory(2,t); + char* current_dir = new char[cdl]; + if(current_dir){ + if(GetCurrentDirectory(cdl,current_dir)){ + for(int argi=1;argiStgCreateDocfile( wfile, STGM_CREATE|STGM_WRITE|STGM_SHARE_EXCLUSIVE, 0, &is ); + else + r = StgCreateDocfile( wfile, STGM_CREATE|STGM_WRITE|STGM_SHARE_EXCLUSIVE, 0, &is ); + + if( r == S_OK || is ){ + EnumFolder( argv[argi], is ); + is->Release(); is = NULL; + if( options.its && ITStorage && options.compress ){ + r = ITStorage->Compact( wfile, options.compression ); + if(r!=S_OK) fputs("Could not compress the specified file - Ignoring & continuing\n",stderr); + } + } else fputs("Could not create the specified file - Ignoring & continuing\n",stderr); + } else fputs("Could not convert the path to Unicode for the Unicode only StgOpenStorage - Ignoring & continuing\n",stderr); + delete[]wfile; wfile = NULL; + } else fputs("Could not alloc memory for the Unicode filename for the Unicode only StgCreateDocfile - Ignoring & continuing",stderr); + delete[]file; file = NULL; + } else fputs("Could not alloc memory for the filename - Ignoring & continuing",stderr); + } else fputs("Could not enter (directory) - Ignoring & continuing\n",stderr); + } else fputs("Could not enter (directory) - Ignoring & continuing\n",stderr); + } else fputs("Could not reset current directory - Ignoring & continuing\n",stderr); + } + } else fputs("Could not get current directory - Failed\n",stderr); + } else fputs("Could not allocate memory for current directory - Failed\n",stderr); + if( ITStorage ) ITStorage->Release(); + CoUninitialize(); + fflush(stderr); + return 0; +} + +void EnumFolder(char*fo, IStorage* is){ + if(SetCurrentDirectory(fo)){ + HANDLE ff;WIN32_FIND_DATA wfd; + ff = FindFirstFile("*",&wfd); + if(ff!=INVALID_HANDLE_VALUE&&ff!=0){ + do{ + if( strcmp(wfd.cFileName,".") == 0 || strcmp(wfd.cFileName,"..") == 0 ) continue; + DWORD len = strlen(wfd.cFileName)+1; + DWORD wlen = MultiByteToWideChar(CP_ACP,0,wfd.cFileName,len,NULL,0); + WCHAR* wpath = new WCHAR[len]; + if(wpath){ + if(MultiByteToWideChar(CP_ACP,0,wfd.cFileName,len,wpath,wlen)){ + if(wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY){ + IStorage* is2 = NULL; + r = is->CreateStorage(wpath,STGM_WRITE|STGM_SHARE_EXCLUSIVE,0,0,&is2); + if( r == S_OK && is2 ){ + EnumFolder(wfd.cFileName,is2); + //if(S_OK!=is2->SetStateBits(wfd.dwFileAttributes)) fputs("Could not set state bits (directory) - Ignoring & continuing\n",stderr); + is2->Release(); is2 = NULL; + } else fputs("Could not create (directory) - Ignoring & continuing\n",stderr); + } else { + IStream* is2 = NULL; + r = is->CreateStream(wpath,STGM_WRITE|STGM_SHARE_EXCLUSIVE,0,0,&is2); + if( r == S_OK && is2 ){ + HANDLE f = CreateFile(wfd.cFileName,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL); + if(f!=INVALID_HANDLE_VALUE&&f!=0/*Fucking lying MSDN*/){ + ULARGE_INTEGER fs={wfd.nFileSizeLow,wfd.nFileSizeHigh},i={0}; + is2->SetSize(fs); + BYTE* p; + DWORD nobm = (DWORD)fs.QuadPart, nobr, nobw; + for(;;){ + p = new BYTE[nobm]; if(p)break; + nobm/=2; if(!nobm)break; + } + if(p){ + bool err = false; + do{ + if(!ReadFile(f,p,nobm,&nobr,NULL)||nobm!=nobr){fputs("Read error (file) - terminating this file\n",stderr);err=true;}//read less than asked and there was an error other than EOF - MSDN says that the compound file implementation of Read returns S_OK if the end of the stream was reached during the read + nobw=0; + r=is2->Write(p,nobr,&nobw); + i.QuadPart+=nobw; + if(r!=S_OK||nobr!=nobw){fputs("Write error (file) - terminating this file\n",stderr);err=true;} + } while (i.QuadPartRelease(); is2 = NULL; + } else fputs("Could not create (file) - Ignoring & continuing\n",stderr); + } + if(S_OK!=is->SetElementTimes(wpath,&wfd.ftCreationTime,&wfd.ftLastAccessTime,&wfd.ftLastWriteTime)) fputs("Could not set the creation, last modification or last access time - Ignoring & continuing\n",stderr); + } + } + } while(FindNextFile(ff,&wfd)); + FindClose(ff); + } + SetCurrentDirectory(".."); + } else fputs("Could not enter (directory) - Ignoring & continuing\n",stderr); +} diff --git a/st2gpx/libexpat.dll b/st2gpx/libexpat.dll new file mode 100644 index 0000000000000000000000000000000000000000..4c925de3579d7bc74ea0c85f4d096d0070e09da1 GIT binary patch literal 143360 zcmeEvdth6|mG_mUIEoR`O(KE-0|Hbq*aR1+Z4w!3Cw`GQwq(arN)jifur(pHS&$&R z4Z%T@7)|O(~^aw(U}AVKIeLI}UaNE#%P$ZQ3n#`;cpB!#kmXzTa==UP*S6 zZg;=k|8O$8_s*R;bIzGFXU?2?+@)7;*X)|6IS{g0O&h?Ke>L*=Z~tWQdivSlpRPSJ z?Z@W~*qVQQ&a$p+Z}hFd;j^E<;gi?py$- zHFHirxx{aR_CEQ?jVpg`Tw;Z)UAJAb3eUe8+Hy$~u2s9@ms}&?_g-=)u9xrn;w7tb zz4HCIyngMyv`pW2?Wej3<3tz->ou*}=FndK+MOS_(!8imKj$P{v8LT?)3og>cGIVE zujBq9TzSWP1oDS})>W%1Qt1$fJNzLL)8?+~ar@70+9Ic>IS<;jGQK|1pRY*E%s$b} zzYz~SfAlwA&xu~MA&U14?lkEltrE|CCZDFQnRCO{pNxJ|(+-k@q`lI-=95t-YUZe9 z+U}3w#fxS-UJL$eG;MIs4cDyu?58ws*O_<$+B6@oy5bb><4v z2R`7y2ORi-10QhU0}gz^fe$$F0S7+d!2dA^M4jKUR$HqDGnb;I_-@zm_6dJtnctDB z^E=bcerGSPp|x6DW@vCgko9STPR<6XbQxH5WvwnKt*1YUP1 z0*DdyT6&Yqm@1Y!j8=!}a2gTk_=TA(L$-XnSxAROqf^VSvgxCZj-#EtICWgQG`ur9 zokpi`v}XhEIU3HM3N!-4Mo$6}vFYJ#*dy^;-MMPTa2H4YR*Hs-m{-VTK_pTMomGP} zp=hZ9KYW{qm;umQD&2|gfNu1xAwGTg;5QO7c1CeEcCM4Z`{eJB_}jVB*m(rWM|ysO z$8&mjl6Ad1Um=8@y)xZa{PynLj^E60KMRokkKi`amiZ|j#74hA63%=P$>Y1dfxkvu z=I^A7Ce{$n)WgdGf`Db!;ELf$<|9|jXHrbm+{xA1Y*vIT+CbA}>Rc9e8~vq#dd`Tf zQd`Eh*apgehZ0g#dnL+ZM6x0Cu^Q`*8Iu>O_OOWhUFjZH!f1~dzuOmTdN6bKO(3Ao z@2NT@D(Eu28|xllkO)^+tWRF;?fp0c3urAnS&oknP(ZD4x@9f z(K*lPtTsApjLtfvv&raeHadew=Q5*nxzV}O=v-rTUTt)C8J+8l&h^GkQKNH%v9lY{ zjGYPj+be&!;#ahwa*Y=XJ`P(Fa zo8@m1zr8zG%HLItv7x;gwGLxvseJE~zkc~!CVwmNJJM5$Uz@RWu8iuEzw71iM)`YK zBKxlVeMA1ffcV~>zmmVdmT6wZZ|4d$FtXn%dYB?P7fg2<;o??pF&sK|mBGDGkT#IOJU#zR0d?;fB)g=dg2qcidnsWY01&NnIGFAsaly<+5CnFqmq_*-3lXyk z#9!`e?;uheB2|N;Wu6FE8=zmb)ZkJoTAGYyeh6C~p8TREh$o*2H{+>7w5-8XnFz1M z(_GQgg{Mjpz8X)}qGdgv0Bjwe>O{*%Jk^Ns20S&3J}J}7{7s_28^|JVndqZzBT-QF zOIdIBuM{l~L@XEm%Rq>DY7Kso^lH%(Mf93fKc!G~&J}YI+a>xucs)e0SF{#GsUNgKo!bG}hp;%xIm57@rZTMx@_p zY)0f9#uT`MsCC9;Y>MI$KLPe`lS~FLd+#CxlW!SYBzL!w+tCm*M8!7N zOgchlW&XUzY--VS!;#GP6;k#f-Ja1clx|A07`1p7$(8L4Ya{co!R6VQM5)p~I+gun zB={4`UuFcCPkNuDciE)!Rl+=eD<{2Qqn;n!~itRr1w}VKfpgfJ9Qrt|;)8j*wvaBEaq=qE4CzaXHkyU#~<`*CgdI{Ma9NnN4k9bz>kBB3{ zz&A8j^!nGuGr{;v_V(BB@5r1aQ@f;LuiCp)+3*q3=@;Qr`wRAcFo;2hR}705@7ph& zF__-ueS6<|qedSQ4z`8DG@8T5!Mh4{pD#`oJ+$bReGL`PTy3FXHaJ&cSf(5Oj9A@i zapkxauI}W(2IEH{;)H><$R}8HVzhjh z*t7X4hijXrJkE=K%vc9X)*;KE=Hu?xs=yw1`e#6|e8~Q)I1)}f76jWeAF0D&b4jUK z%WmpUeNW`8|c&4U=LM^?1zgXmC ze?!7hmS`^(KQ4bB1=;r)i=6iT_RMPII&Y`ZUb;%`0&+`A8I5;dAT1UFZEo#VbM!QitQvNBzoB>&<-+X=45Wd| zNLIdR(+jyau>5z3U`qAJ^kFpZ#{p9NKI|dQa6d)=jS+DeH^ZJTNXs0uk$vp}K>gYy z_!+pD@J(2}NPdPh*OU@tU=lkQC3qkuI(t~Sf5J-ltcU5DaibhmNnsgM-w}u&fxkkB zTghWk0c|0%q4qFZy#ra|N8XRFh#$#DKNdeS9VL{;Jk(Qx*JBuaMV&^aYVX1Ja70hM%j>fcOeqdkpTI#B|?XQXU zvhw|b*ETH(hq4`P7GVD}vBV|X{jd$~#v+$kqC@)K%)PICKc4K*7)x~MJ!6sISW;#m z6-%7rMu*rhjufglW06CgfsUdFis~WTieX$XmAal}#$Rq`6|JP(a5>OSt^u0Rus)Hb zLCAtH+N!MTu<`ebR$w7DGQ4}SX zIskOdT3efRg}BBvfIwbkWV=~czQ?{R6hzr&u#MY;nFcsK%rUP!ap^QX0Ee~k9cI2A z!NXystUyVr-p!y<1lJ_?8o`xtw)WnJ=fvLF*%)%n5%n8b{zp{#;fPsu60JY^mOF6= zP)IeLl|Ygm^0pMW$-9VH0|dgI{DQni8+RwZ3b3gp%~1@w=1RcPSz@~AfbTfeM(>Vm z>|($b^+6^-m$ypr)&)aj)9^UbP-+u9$o4db72UuEQ)JPMWJLv_QV-G>}Mg4k++!Y-xD&x6ADkvr; zMt>$o7=E_6+C*4~&K331V76m@d^fsccj5`YPJbKljPwKe9a|&eNn$#93yGj)v<1hi z`S|EMB*KudL`*l*ydN)LTbb=}(e3RZb2kCtS|4KYY&7^;#?^?55BiLTvUEd5)m{i! z1;lL!o0T!!cvN0nbfd+icw(6stvp9}JsYz9+uB6#g0dOS%HjM>|DJS^1v*FNK1L1k$=}s_w+IB&->J zlm>s=!#=FkJ_Mr;(BY3NTa0S+wgrK}`bfxvz6@R|_%gu6@_m8lfkSERKCr2j?)e6< zXz^1{4L7*w4Ms+a2tFEu1^P#_LUKNNrDXJ6RNMt(M*=hocN@gY6sq)&dl1!@nf(b_ zn`3)vPf^CAp1gbkVDTcp*RAA#T&|LTk;!kYL;36MuZ;pRh_M!K9|6N`=^qd@xN9E? zhT9{VgI6+-7v$Elwtj$qLL?~*Ai2~?QZ^_7U~nD82W3*oO(J$Mas6B&Wd}}3DM``O zOoHH5Dj@07!EsKgbcv<&pbY)U25MXY?FX73;e;Io6vR>otc#9$sGIS#p-j%OsLlx@ zFwn7j4pc`nZ&N8iS;-zbS}T@ziNgRsQ|O`y%nY_=_p<;16EzNzj)E4@S!%%J_b4C4 zY|-E}7IGlW5y%f!3nUwc!NIY1ED%N2U9F-6L+->b5-delBq{!Asa;~Wp@g}Z{5E70 z5liaQj>S@w`oU_nb>IL1Nx_=Ie1g~`Myd{o^^VuS;ZEMf$TS6A)X%$ueB^y}Jvz>= zR8o2m2hn6;KYdFX0H8$CUh{t3V! z#q=68X^X9Ar``RG5LL5Uf*9Mc?}MAiS-o#TLUgj9?vf1F%*hZG*!UB zGlCT+rwh2;;xraJWd7J-p2?ly@7SM7HWg8Naj|#rPnFl`sXre2z_n z?qY9J-3A3#4GA3kp5&NRRuouNl|Hsj#-Rg>o(>5>?yj}AP}>L`h$Tv0Z^~!7k++cT zP;jhM#x^0_N#Kg|+mD~BgirQVp*9HKU2r5q@Q^18$a)YOp(Ar2tUVMBDf7Tbl=x*4 zh&s)}!kzd&Dkat4lsMo{ev$RlQ6cIpp)$HaN>{KA>LnUt4_Ym@`n#C`zGY*&sIMsB zM{Ny{T1PcJ!yJ{Pl*;&S9|e)il_5tS%m)5%0E|60el5%oSOn$!F}yH2;2K}1IIwg) zp!fuGU$2%tU?aI5RE~dGS^;Fl*k!plH}lOg>|1`h#Xg#59vUAIaX*^mI>R>h&u^on z12<3ylH-OBg9n4#`0nOm<8ocP5{o9aO9CXE`L=bZn zr(4A_5xN1Dh!6BR$ddTrEqrhlK5%%EOLmI&5YBdR?p6+DkUvK#h*}S!(qRC1WUi@{ zRginnYJl0GQ0#fQ(+eMF9GFfOVreBr zK8o6ohNRe|nke>oqb5SoUSU&0X|r|v#@WTL6F;9QkcBdZ-o7K_P~r$8u7(Dmg{#My zNA~3^d%iTQ+=&M{&&FZbe7-)}q9}cZcEu%{{@%r!-jA?uj;1#v%tiRf1uDE$rs)i2 z7is!c6`KC5a!sFw>&HK&>1o_oBHu-Tu^3lt2ois}jP`jo?en=|OnE&@13d!js}b~| zu%|b9f)R8e)tP5`q+ZauM)yc#d*;zYf!)swwWbT=eXJUd> z`emer&OamAk-1Sa=vXKsDXk9nz3B~rjn-HPglohN=n*3AK&&F$PAjO)J|Z4v3TVE- z$fkPLyT=E0BgxpI7unC6*3=|S!EUc1%LzQU$rThs!3e6nOsP<>c$65xB#!!hFl#sZ zYutU$AO?4J;(d{p_|YcVFXq~Wqln_7td@?<^`MGIC;Ue4L@NYW6sMZ9iM{S5CzwZS zvNlLUwU}N5D@>YKWIUqk?7QNlj#QHiLb);3;v9i_U<0S-qJ@-J?M)uobP?`6qRj&p zT@ko6>Z*64d`S8^zE9Whh( zHSl03W$d6uH9iMn*enrB$VDDp`wG9;dN`!%a#m1|~{U z&GJ3Qj*WN)KUZKB*n3lpvK%K?4F-O`$uFLpe_GTPA1sOwIRm@E<(WpZn=C3Bl~=6K zV7E|8`3Q`<`yK#rN=SNcKd`0tsuLlPaOw74Vn*u9Y~oO?Q!IC4#2yj<#$Co5>q?h!xOiu=tkWkFK9bmmid&<_6f z;2*HqAnLD+t`n~vd_T44{h{78^T77f#jb-#a?gXY!`(;iH%=XqAnhrcN&)$U*wKqD z1e12%H1tvt#udkJqDGPl$HAzWFaCTMg`Adl+%)uJkx27JJmYE^bvRiGu~$G&bt}wM zthX^F>h8WD!P)^aK8Q*wYe`ggZ^{0lEKvVmEFsBZx)qm+=`i88k zmGfSQrv!TBrnDy|N&?TjlfB3nxY7~3K`^p)t3}l;xF04)dtIUF|OId^IYF!LXK!7WJmgq)_TCPV62}YP&Y*ZRa6+_x)0jxJZUyGKodqN|I ztGntI$oRBW-5gszQoPNC<_))HBf7H4Bp@<( z#W0zIu2B-_Ft#w?cnW*30`J81^iG;D z=?DGzHSFWl#LfynU*|CFV7)$y2T78jG-50j$wufbgyUMx+f*1!HTM=a<*Eaz?N?u} z=~@4dCR{{=@rUfVkSB~D13l=*7PX{=N zneqZKi8&}QNC1?rp{+{bQJ7)u=tm9P5#G8?)4y7+>1z?bh5MZdTCq(lD(0WvAuoU9 zXG%fa;w=T$sTProz6^>>3=RZW+Vt3zfqUC*dMGU$T)LlYfla3|Xi*C_5?I%!9T*w+%Ob{&@LQ zgJJDF-c+RJ9Ce#ejS1?TEv=~?&IbD1z+lxiN~H^JFr0iPb|F%DLHd(CZ@i_hM!}?b=NBh2X-y=v4hnZYaffa)9 zE<*YvaSX$<69%Q8VbMQ`q(=X4!iOXQ;-xAZM00L=untqtX>*zGzY_|yxDG8ogOY(f z?BM~0>pnRC2sp-6A^J7516d_Sc~0FA&^az{{JC^(w%d)Y?uhg;@1Z<&&R z*#qd6l7p+=33h9l8W)_y*|6+Y<$7%J_Cq4!Ck9~e$tc5tTjkZ2RoJ>?AG`PPu@yp8^MfrqLfER{BapAdtYNNgpt zn!RlA;mj0R_cR(#xV~Vp9(`k0HtY%O3(Wja|JBOBO078@>5ii`o9OX?>%gDNQ)*}k zf(!l%voj7Z0@!&-2`c4E#N(t{Q-?I{9%UK}aq}we0l9~Tn8@`FSX57=0IuPncn_yv9BXy84{x@5;~K!w4N7tYRBwRs9uffuF?*wPR}0A}-S)yt*(rFDoF1Pe?bpCS5aBf_@vq_LZ&4i@S<6uA-> z3hrT4!yFrdQ^b~h#n5lP5RshobS7VMC+EO|NY^{!M;td##gdAFm9P_GOuqeV0INhk zid|(}NbMJbD6=X(D50Vze&jOume)}%vi*qJP)J)l1^2Wgrr^4hKf^nDw*qdj%_<=<#ejd?fr zDcnfF?!+42_A`y><9n?65dDN0g5k#HA8J+ms4RtG+A{MNuqwP`G84MXU^|!Qv|%1d zN|rl0MIyq=16zD!rGPfl!v)@0y1yB}Hbqnoi1LvSqPDJlpM4n9^^!Ks8@?Hk;$=wW zN!!1H@yF1%)|Zys8M@xZR=u`N%}1EYW%SHLQOvY~nd+c7!Mq@D{GoOjAF!yQ&D@DM zq0duWx`7Xdj?09Z3uekOSTzQL(p5l7WSI9Acj7ES?#Q&#UhQLPG;6QLZh@6XWR2*d z#gEp1K?>CX*k>!#f~y^A(bJUnVI&gHWR;pjTp6UV60NintrVMFOjIdbn4i=|X6!1t z+ep=Pv_kYr-uKH2bf%|d9nc5&Eg)!BMbC>S zx3(ctG^{6U61bhj-2beS%;np2&=ymDtWS8gr-{C+ac4B?BU{*I!ByyiN1;swb?&P{E(P2ORHV#7LW7By6m{ir*kBdsYlqG366{~JBpVTWA5 z;}{#^lj5k4Dn1iZ)09TfGLxWx0)#OR#H5U&LAAA`Z~4=CBm~W7xtXj@7PJyiXd+F# z;BTad6B63^x{)5fv6*ikw&~-aQ18qrC!-qFYZvbqsCy6Z=cxNq-k+=P{k)&8?kjm; zqVDJ6-jYUl;u%@ptOgSPB%a28hM#D?P_ zt;)$N`l;1K&;9t7zDslW+F6ne>AT!Y;7a+~E;Q5kG5tcZ%aGa8ADn7!(fR$yh?UIP zF0qnYlSS~R#*h~w6{yiiz8aDX;1dVydevb3sNa3(V9+>ytu}_8oH<3}PPj=IR7e_b z7^Iz>Q*J3KN%XS34ef#E3A&TNbfeJEt`V&(!$vE1tw}aY=E3@s>?9L=&bBfn?q`M^ z6YqoFm}lahc>3=%@fWhbB`+EY{O@Msz4?sOC02hY6D0$U)4`mI_&ev5jU7TVS@g3_ zn!6lIihmqH!AMzn6g zmLCy`;zqqF-){t+qBUwTLMiWP9qXAp&DUx`RdxjD=ZgLAG6d~Gi49D0gMo=xPN0CY?j zNcF)4>;ZH7^ju*o^}J@a)FuJ_yNe>EI>}f$^!yg`S9YSo%wN%`P3T0cQ0!<8B(_k< z&*dh^TtDmK(`4qSWv^KQDy%M2H)>rbC!1VcbMpcb>6hIHdW*)D*zY*@6s)0qweG@G zzMMzold2%N7WjmrEGple_99+PE5(Jw7sfKusJ+HD=Lc7BlggJwu2-ldqM`d-en#Q&wO`eDKM4ncb>;coQ zK`4|Rmm_f@j$Z1 zSd4Adn2_7)6Y#6^b#pLN7K|qQ))zs;+w%o~0B4*KA!5P-Dv_ zyfsGS$^t(78QHQ16XJV}o*<|*dYbX;PMpLSd8#an{cI2>n>15Vn10Ts(o)|lV}0z^ zH<6K^I~X>w>fli-v{-pCqmV@~^Ea6Gm{w<5(BG>pVB%*{PDkcmn479JnyU{=gk={u z_Rj=m0*>Ay8rDFdZaOjS2wHs|jpZAT+tuSjL&l~(Pa{?<-zT=*kL##oJ6ENN zo^JfIxFi6MeFZ;?MA1*O(~cP_*NpC?8{LUF;Ex#5D)JaCW7=Hy24-I)qa+U`$|;Al zy271!99dJ_?nOZu0xZHr+{aBsB^N~9_IJfy#3}7kDDFu+Qo@yrAGJqM8P$+Ehh}t& ztoBK4**G@%8gbDj=b|UYH)2(fJ8>fjoHTBU1yXn226(-9b>r9S0^P}O=I5}&orv+) zobDiF6ORIcvDJ({ruoQD>t@KF={|NRs!--yEiDyLdnj}0e7wUTFT?Hl568;18-|dgZtkG7k&C+MWCoUW$edq-{HITO4a`?b2`R8rvz~VOSS! zw?=4~*{yeprFz>)J$5;Sqd}gMqef|nk+QSOL1uEKCaZ^AE$+pDtFZL3IzTRD{+NeF z<>aTBPlW@thalS2-CU+52WgOb6k}|oh#T7;VqshE#jkB_>@dsXJzK_;c(UL|Ti1Hf zt_a6L?R+O7(0x;NApYKku~0*d_R>Iy64(36!UeyPhcGWy%vwnI~xcFN!so z5tvFDEU&E#)8mu*aRm{Rt)E%UMpW@Ma%<%oBrP5KeNkxCaS^D7R=S_R@aP*W%eauu zPu;ip5~&y|3mXVxn@ofS^cOl)dg6dwh!AyJOAu_^9w3ZdrGFN)Ddw~zq-jimuAZ|Hy(S&T}|e(HLF8@q!Ea@{gIkw5FX1kFrv z0}{mFo9<37#?9E(OiuTkJF$Sz%kY!8TrS{SbF|=2oW=xIjAG~MPE6zTdHBI>kXJ1n zcJh>gO89||8P-B%XWlK0ww`xu^8xkgQ|?Sm|8gmUTvP2F&K(I;PRT*4vQTjIhz4;B zu6O%{=C}%e&;GIsll|Dg3Rj6J%C#Ekar4w8&Q*#t2=QQB2A~zR@_c<3O#oY z`3LjUop7;z{oSr0HMa*hp^1dlH1G+PTUs=R`8fK7PA^d0D${H$6Sz5-IU6Du zAf$dH{g7aoB33+Y-o@W@VWq^=tK*qcwLaW`WJP?i#9|Lz9SRw>A#~p=4KsNr4EXM$ zj`Q4uQJjD97CyMF2We4S07UjrS8Dp_8#Mjbxb8#v0YU(7;Hz-mi}=tAO<#}uS8@MD zi>41WVqG%AyG@!tC8X&i2;F!;9q(>w)$|V|{`a`f3u68n@wc~W`jzdPem}y0;{GFx zHT@qE5(sx8d=23{2u~o4A{<0`-weOTbvi_9$c&qC(ISb>h|+7W~Onf z7PfgI23+POxAA(7sdzLeg@COeLOzZAgXK&MU(tw@NsoOcTdkb)l8Y=1?8(Or*;uEh zKZo!XLO+577-_KeiX4CMpFLM4xv4-GriNslU}(1;7==0_LDe$W0KD-OnK=p-g;yG; z#K61wpc^#DkDO)nk;m>WU&bpk%87Fwu&CyDYq+R}mVAo|G6Eg_SF|N$8~-TWJ}f5! zr%j`@eRQgouOn*wbTtviiKVTAh-ehH?(h44d!rFhnyxj&n;$nMBJIj1;_ol|r58GqSa zJ>}zcU>TW%QBv7RBMiSD3cn$ZRk7M3KI?=D;;kCAkK?K%pyq!EjM_TdIq_K`Yk8jN zXB^xr!43|?HvUd_sTgTh0Hz6zQi(d{tSZRh$Z2e8E|0>o!C?U3>HE*Wt+N>`mj!skuK~3gfIByaK?Ksv%rCg9fS?85mZ@& zs|IN>rN3g>I)=mKNC*Xca|*)4iC&+GuK^>#8gB%%G992CJ7INefmpeF%Qo6k-~gOT zy-oi>VNUyT33p^WD$spE7PlTk(@dceVC`NhobH&`ZFPzLGS%mpv|-y8Um*h^r&aZw(y@PdF|n+1!)NLbLBm<$}jWMKReM0Er+nLIUVCW83z* zTU*xEtsLj^*4(nrhT1drm}x<)Ft>*%XOL#j z8iHyx=TgcMmOp{}Is|%df$07O0LJQ&TXis>7!G`kT2?LuDmCt)7H6MBU4?aa=F4K^ zd;jH&=_&^^0|qnm7W&e6BzFn>jkpC?nn?vO(Z?FXdI_t&02wY>^5-#y#a{5z z#8mc%C?8m0ZQuNBG=0IRu+t6KT7)xkzX;*;2wShxbSK)bMy)B8rUMFdYF>RFdpBW; zU;JgYu!3vuNTDVkTf@qbC*HxV&_}m;@JyEA$is94_S|CWxHIMrX8!R^vn9n&S}l3j z34vul;-@~M^UBBG7lXKVRHVnMM4x*L8{W8s>vO1qoNJ{9`rWk}JpR8zNodTjz;{@! z?!*kXQQ3<8=9KytiZWW!eWg-bDama}v=$4*63Bus*a?$bZ2LBnach>#*v5Gr%I{Bb zO*KfNJ;b*SbTqFQjq7n)2AuVgcpM<$#Pd*3x4@ymV-q5#Lm{#r{x|DHgYOcSOio`y zDZve^*3#SC4H#q77=?}}wf#0c_HLJvZ{QX_bZo@7?~$UZ1|QOSDC? z8|IYu%=P&Keys2;6YZ{4^IT7F3CU@c79iC20d@5lEX3ym#w{2{{SC~f>3yu*z)e$TOK zsSCyvOaWB1v72F99h-0q zisQ`c(iOEGI7iVZj;OA|{$8X5M?ki)2f{Rp7oNE()IY=G4mKX-@)>u?7S&L<|3z$% zjUYFcayZjZusH^C`sGaKMSH`s(`Mdq<}BjX?g)3ZW!q~andi|k(S&k376uitcBGu> zYA)?QdNTGwG}&rka=bn)_N4UgcTSGEM{Fgjpslv1`<;?l@wmNr25#qRv6n_{@`NlL zKmoHiFtqvTo6RB&@*d;9(QmgL5T5%^$vDBg_=&)PmDt|o^ z*eQFcnQ3_xT>3#u2wFMM!FiCKcN*tt6Q7N!Ke;3x?T{PUu%?F1#XL+z^^Tm^n`>ab zQNhakAgJL^Wv;jf;epZEfT}t*@1n~M{AeMVGrCqnG4T3>k+MuQo8Jl$Eq&h}Q zR}KB{>|C3iuue;jvfd^~Vy~=%n7y~&2^3b>8Z9o0uC$N=*`dxf4~vJ^u(DTak(8ZY z*!zK6^#XH2#w{9-*1lM@ti;+J5TU2TIAv~|tYaGDQB01e+`TyPW#z)gz+a8<%Gg2N zGx0toZoq+>SLG5n0?b-xx}h2}$_z*?!fP-V_^kBbvD5Kmnhj@m?vDZEl}5`N?1RCz z-jP~l!|X%UHKvAhxiK^l#~2zES?&LOq$L8ZM9Xq41kuwiFd%;e)h5+_bP17z7;zDN zDNlYuLP!)w5i5Z#4>kJ~(pty*s;1t!)|C#I;V|<((0}YVAsVPL4(~bEpFa<0QnajD z4Me44z&Xg_H7W5jFoU(3I0N{k+}%ev#5%igwOt=u-hFG)x>#HHt@h8vn!9gx+!$*} zMW%2cA+|im7GML|%*`WrBlBuwJYuWYxHPYWB> z$|=BzJ$a%vSYOP;c$hHEQPCN&ki06b*T6_B))y&Ag!ID}^mcdAxjhO>}z;v@Q{ z-2;zJ?4-?4Q)7+MQJ1S|^Hlv$LH12fzMRVoW%jhx8j`eHLs2N#D1Ai{ClIrueBsh_p|a0{n8~}^MT)!QpH^t(ROc*f zq1}*VBYX1}Mc`VEJ>yfPUo8r4#F=;UG4r%^g|Me~jMS9cx&vC&wn){D_^T?2ZNfG7 zlyXJzKtu>0k4H2ebLK_vhY=&)d$;RJ@G*O;IIOdII{y$@!j)`os@TD zC%cp0o%hQ70r^Yg$=Lab{AFKk?0iW6a`JMdryIYv-kqCq>D_r7e)$~|$(s1fPAD+V z+TVb~XNWHm;LeTAD%?R9DoBmtJ4u!o?rO_i&fz8>SlEjEQ06PRk7Rgmq$GShZ%FtS-jMK}EQy5gzzzBaY#l&X z!L3T95Qi9>6o+sJoN-_>OGVY?2q6B=R{fPm2tK6XWAN0L`7%lZ0cDDSkEcHu6dFzm z`h&!nj^)JJuv%bDEn&XZ4iW-V-3ce6VNYP!!<7J`sM`%eMPWEGD)S*yAWI0agbZ`R z#&{T5i$yEN657C?^b({zq-2AN?h)D%?JE(@cHRy{ynQ89EE0wD_-sR>8d$#VWze+G z(WJ7v(iq;P>YcrfPC+v!TA5lpE!|Hs>1~}Ru6G3f6mzEId>)@Emcjv*Zm)(p#6=W9 z58s_o!kU6A$#vkZ=;zWc9#V>=JTM4};7hy4OeCq2A6Z(er5ACV2J2Ujhun$ZK~b&s zrrSNh)L)3{v(#Yq6q&OjR{pf31}9boxiQLNG*ay*?qdp04b-C&u<{H(H&6@|egz^W zwjdHX<3A?n{KUoOLTa!{>^czaHbbw-aeB?Qo)l1 zT!v$|sP~9gPik4Eqj%YK2cPOHS^S5BAPxI{NOLRFV%lK36S+j)Y$+n|lBFk!M$c$n zF{no>lnLK@O?*Tha#Ol-3yGm@;QK_yNC1J52GY|skUj@@M0;izGEz)H{kL$d6kIx< zz&#F^&3rBYdMj>IeR2G*?iIYG`n&Pldk240JyMIs`J3vyjq!rNss4L;e+PeIh~n3X z^B27l?*)HhI`IAu{)!%{EaUtYeQa)>hTtW)nb$dtZ*r*irYsoh42%~*y%+j2LKRW< z3YPV)^LsNMOu9jeO4~9Q;ZFKF18=$$hY6hCx*Tg!sS@PEl>a;>h+)naoLX4WX6b%TD-!n4Ca}&OpBJ=kiqZA#^1-0CCs}{wA9#lz#ScFbWgmw!$?b3QFbruY zdWS{5`Y72*y`y-v-dO``FgK`7Q*4B^zIx*wew?qW2C-Whi*7=hK?=L$0yrdsXbR5{1dlA(@FULpggS!lU$`>1rR7zr}Z5C16|5+_j}XT zkAiY7-IRAJVV{^FZtjVB!}C-#&2O&w;FX7NF1F-~Eh@ ziSR0Sq|l8#pxlek102Rx=dnTr5&HqSPa9geZZ}*HL0@>qGr*`8YnzGCZJ*_k18nQi zgV{DGyl-+#atdA&174Ze;Y~a5?cNRtFuQb6cpm0KMmYDh4)r8w%)~H1v5;Pz#bHMh zwc{LibR&Jj-rQkFP*?HlhdK1bIR+@VJmFs*o3*XY{H_HAVT(d=t7c4-v@&Vpr_&YK|{4tx=0n zA}^9FqqVYkn^2&1XS>8yLP6&!D)He1azTv1t^Q}x$gX)N`%1iM%fHAm*zyl9a;2|> zhKYq7^K2Fj&~Pl?1?`zHf)$I{y4> z`E|Dj9Kj9H7DVe?C+wkOv%(qL29g$Q#Dk)6w#KGQ(5BR+omu2TD`E8KERy3y6xq56 zWhS$?{uFVLTv^nFAzL1Qj_)olBw}+8;%tkEunR7wu!~8jjvurL$YX!}^Mb;eu$t=w zN%;6ut_)1rVM^5`PaUDs;^MekE&l+%{8*ql|Kot0-ks<}dU>pW>_Qx1|t_;NKR>^slV2;154yk$a`EqE8Q}DLPZ4|V+<*8cyuqPEE ziNqNrAQERHNHegH<7DjBSgppEfoG$ahf$ajBTx~a62H&{+F<&2G?<4 zS2t{btC(D>Q3>9M6o#}$MGp%~2W{q-1*4zOqMtTu`JQxjO7zhbMfsPDeVemz?v8ZDn=0Ed~7Dw9xsxE>99Fab^c?0uI!ck%r zt7uVIg2^cdy00US*g^pCLv@F7<`SpSQ>XQwF6K2F^HMV~gE50AA@-h{i(t30 z8hXV*1Lc%yk{KZ(%beWzBohNmt<6n_76F1y)5M z2RaqZ8`_-EIxnGhwSe_BL3j z_E7)2(hYCMkIZy$=_entLL`I4SfjQF7uq(XMOsS3o@J=cI={1X6oWA=FeWHY>^cWN zhCAv&#L5rh4a}1fG8ePRGiAEgVgEQ;>%)0RY1d*N3AIiD_p%h^b!lw|T2-*}|QIUO0 z!JmWj&)n5A<2FK7ZM4X87=aq!EQJSG{_Zdjd9vOBv1$Y4ogF3CB`gpd35RDwdp(z zCT!Lr7iG#Ew(VPygO!O7NxzFapO^||jTQxw1klY?EDP&wek&)W zW+B{xfHleHl4QH3erSI?)3p@eo9A$?a3w%vt#BzW_#T(6O;wpB$$@r|6DhWKjEb&P z#d6)(pHape2;&IvAd~$+}ijE>4v8@SR9|juarKjsC5)m0v*G3vy{Q$EIz_31;vPq{ZA81e3x?t)=d$ zuGC$%f@C#_Zep!O87!rcUMAG3sqH=tE%7Y1&x^<32J} zhsc~}kl+gCcV-S$qyUuMxH4*c@pcM|1gJ8azoxvz-*ZQzOXKg&jQZm5oe{f{?2`JU z@+<6joXj}DK^WwQ>uyf0Mv!q-tK6;>1hXAijabU&utg@|qSiXvGGCI@R%Q*Ipncw~ z(kRu5St@XwB_5By{B#{iyz~#SuSx z{>_U>43y;U8vqa27%hf>zM0nYXrlRFS&1=li>I%D2_kje^Ho*>l1G*}fiSaHkDLEr z3iB&@)S&E+n?I+2K3u4Ot|@?UBH20~xZ~@OQwyLCpc6v-*e>y*_MNDJ3hV1)=#SX) zzehg=(M3>)D{X!pGsDskI{Olp%G3{^gH8dj|7LweR2ropV6_o{02-E%CgN|^2jsP& z|F`lN$}6#ur+Q8RlkX3fvOdb=nUY+muuo2{O%nS&7-V%EudX;$%avi_cdY$*g9V*J zcdjI|atDcI*PA1f_@!%MJDz@XHSMdrkp!xv7nc*2FY}{ZSX+ZgHh^_{+OTPDy{9Gu zhqqsaH%kz@5H=uab{Oo({VSTF&-hJvuING=ibQdSO zpeRU%lhZJ5&W_C%ybGjRWnff*!YPuYMf%;?1vz*sN7i)k;}xb4rzpB9b%mp6^iO&I zeu(`26|e_?_u--{0zkk>jiq55OOBC`z(}CV_!bgAj4*_t6&2Yqf;i5fEyqKEllrGB ze&iI|58j-Ty~>2hYL!L9hyW?lei$txS0_q_0%^fxE#yF*S^#R))@^Z$LS>~#(Rux@ zzK>_xyFO4kY8ynRNunqVwDKQ||9!A9eIMa@Sj1GJVF_R46Cm|rBr7mKBmX6)rV92r{*`fx{Q`s8ox*Qla*@vZb zH<#2>RWhkxC5730HvroY@@UOGRB0O>Mx{WGlp`b4X0!?|n!`8_^$s4^4J6p7Q+tBJD(u zHnf2X{7kYFH-a051IaV;8I^&_F~Gn@GGo{Bzbo;Dsub`PcKtPK5>)b!%vD1QaM1J@ zPyxEPd;?iHc=mot4u*~ZXPFW<87dqodAr^~*_NZg{!D>gcRlU8fpS2AlcNRzs2*T? z)i~(j7}eI_17M`wjMpl^jEE{30Ua^$5t-A*SeE7-m@6ZSRD=YjvV7Fa0=ulwA=?D( zvLJB%8bSm?AUuNbG{Vmi{)nJWoobs}GXl&oyq#RSfX-F^qhS3i^!)0#_S+|h2a)k@f~n%s_Tb4(bJ z+ohQ2e#lhXSI5fhZ6;)?-^kZdn-4snB(GNf1=Nq|)crZ7w$RFd0(zh}F-!uQ6B)HdXtfN zK&;3}_%*OPS-%hAc7*RD>_Rwz@LL3}7z0)Osq^Y_VEq(p%&O`=hySVWEsp|U(%{En z0W>&pnLq=E4UX8!ClCS9c)a&HSvbM_OA2^&y!@5cd$R>yDxcYfeHeEbmw`svg<BvjG>Sf=(DJ_SKB7otGg$uo*9rQ zjAsYIDyS8@O}ZXACW+MpXi#O+v!X^0`#}KEov70-`TS7)$Z0vz{1=tdlqJ`w#t|VT z3WKa+zK1WSq(5ER7Wp1ORJzRC?wxbu$TJrle&L==> zWS*aC{=gmfDo)mk;|PBX6?vV^A<|oQplYxka}FsRmI3S=`cqN-w^Ok|@-P7TQuX!{Sx3 zC;nS^)gera4gJ;;f5}bA_moJ`&jDiEbGH~7%1nvBXfwa+mG%UMV~2!2GHJ%=zry#i z|2upM`oE8Fo!{9#Z`Tcas>b#}cXXP6uzE0Rr>mAc9G3k{s60 zPL?35237v}ND)3N`_uBD#ow_{&eK(p2X3#`Mx|1U@e%v@N5qdY6Mob&InTO+JRk~_ z{)!-s)y8e03VX%gD}SGDEHyn%!X(!6TwE>R zDQu0eL4P4UZ-(#R2VIZ*Pa}K@f$xqY?p$2EfH}iLGw}Y;h%dqQd<5$~uWDhpN1oLm zczc38p<9vibRf0N*(`QRd1?VO!JC!;BF!})RRilJ;SAj6#)0>_x96yFC$}L=NoIVwDE@TO_@^PC z?yYy5DRVTqlS!G9avC4D$Dg*3Uq)$NNO(D{V^vC8V{QcD6%%O7s3?*O3*-Z#H zAUuHZD+Jwq_fgz`5@88=Q5fFB`)-79BK!oQ@LgetJxPD&6yh=3bMUWlZn(Ex4~e49 zy7gbB&AJ|!hOyhhLZxjc3K$yva-^49Eq1cxM_$_$jjvLgaH4=A&q^zgJHZnKsLU=^ z3UH!aAt_f$Sl}nhqJztc=dcS|kdD^zPAa%BQ&BZrfTNpC1-Fn2 zZZqEnt#|H38NirI?p%nCd+RDhFb#JPO2pg=ZiQ9iLzKP*jX$;yQIvZ0D4a<$RU8Ot zz)_R!nJuK+QXqwmLu98tpy`((bRjGO(so=^2%p3~=IE`#2CkSabKoETreMtSJkpFK zoP=}>5S}&jmE$@gALrPR4}Wrs4HD|)m>r)ij(&n?nQy>RI?#luOlPQun~c{gWaXIM zsTN;iL-vg3?!TV40((D@79Yh%w_O7Wr=k&K<1=0!of$o?`{-%05=6(w&a z$BPoYi2X5F5T;{{5*qlPT70rBU(kQIJv@j}Eam8T56bp1h)cs5mCt|K9!`?&!RmYe zuGUb?A@l#VHNaWx1zwsv5k^mR{8nMZ8&XsD9Z8LbOGE3}S(Ih!*}b@#&^YilaQ14_ z0vLOnf(W^H;C{%1m;_c{AQl~lrHb=_=i6S@+<9rgi)(3c;6HnK@GmC!k9$B*%+1r`%gvg-lamQk6<` zDK~C(Z*4cz%KtdX_6N$GVULY~k1PN<(2B9fU>a)B;#dJ&718$iE_^Cke6J zy(MAN5ma={!$tNW2O(F)F)z&DGKD!JY51P`J}1!bgF$Xj*2T5`&l;=j4wuQ0d>;;x4SALeUH_3~iRKtHoIg}YQ zKb;rI4}cUR1r7S7^GHm)MAv!_y2+LKEk<_7=(6~H?h4rfG9T*N}JD9z6Ym@AGMDb zV?BTtTS9YmId+*J-4JyRpvJLUM|uu<2vhgbrF?V!q&GFT>gK4kdR=Tf_Cm=m3ZunX zT%kUN!A%<|izm!F%ZJ+IM~ZKmBE3Us!ZT8Ldmp#y3l7FSHMMxN@fGmYqgHa7hU5x< zy>OznYWlbH{;B_ReDxL3!N%l$Oj%&K{9lf*D%nu}rxxXj$5%HWAPvhD4Rdj!GWhx= zW$*~aRymJohW$VG-UU3W>T3L+$xOlk12af~pizUMg3*csN*ur-;UaPgAi=1BR%;RK zE6N=J^uid(TyyHTR*94q2Uhncv@Je@y zff`wxqu>RcuHJIBJlmK)ZiRJpgnlyAVLdGqC9EnhxZh@lO?QNWnh)`6krNzCZFJq) z=pODL9vVH|JFtEoftZ?F^K$g?pg`?Syd`&x*_)2`G#(E6e-=&o*=LjLN9+`__e(2G z^;z?LG(~I~dL%cO3VlLPVIq|s_vz5{T1$%__Eo*cEZ7Psab$!h#7Xy6f!bq;ZxJW? zt2AZqu>v|eEl)b2CwXg{ELB!ON6$3^FP);drGf@XM^sQcU+#(h&HFT2>4^fjNf#`E zTE-J1O^7CZ9fW`p53$k|Sa+)Uvy<|EUE$xuNym{hX0zjH=52+IB+eck=MNGmd2O0c zHuAXxpTvY$HJ>EQ(xkZ43Ycb+u%QEalE+(Qs18d?Y0d~=XBFROi}y&PtA1LS9r#7Nx@9 zjEomWHwy)FEG0pA+Bkr(;*n$7oGbB`m8&3`m6vf;mKT%5+e9hBfC(r~)Jc)Cfjw4|*KZnjC zVFaoGFL5f#^E<$AfjxkHyBPn6acit_oaLf+!pVj>7rMtCe19DH8{iBpI0(*?w#K{X zv6G109@Yywu0J)lM_W$_tdo-uqyu_rlajd?;RvJ1(!qk|{={Cj*HJb}!6H<}G>)oV zu)JTQ+2Jo!{b@}?R#)o>*OwhVD{3j^1`;2MTDMQ-5Z@^|Q0>!LhFFj|LiX7MWbqxx zwL)oMa-FkugP3yaiOKjhH-|C?1)B}rA(M)gDD1!@d{TUl+krr$ceu|CZU;*AH42m7 z(DUKJ(w+y+8?3FV&op`uIY;W5uK1*MG-eYxsMEqMz2@;QXsNXj z<7AC(nmn`#W1titRb#2zmudClX_PpR)_B5IXT)vPZ0aA!6rrn6Dab%V^zWwZ;L2nzQ((=PEHAv zW_FRPojXs(VN|+Wjp(kYMmrE-jmk@nOe@u>ZnhQ1F)}??g;68ZaY`W_WrcC5J1>K) zHL4phZLVz2JBE9Z42`y68~TvLf=H-Ej*OF+1*`$;3C$-*5!pGbStTl4LxV2CjW`N> zd%P)%nOb59Gl8No|Ea?KyVh9Kf%!cOD>eOkBiSnCzhwnWBOfl+h_@^xh&1-4=2N

o`}M#~TH!R_w*#*Mmjd$$ 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 +#include +#include +#include +#include +#include + +#include "gpx.h" +#include "st2gpx.h" +#include "pushpins.h" + +#include "annotations.h" + +// std_anotfile_header[8,9] are variable (number of annotations) +char std_annotfile_header[12] // num annots + = {0x34, 0x12, 0x00, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}; + +char std_annot_linerec_header_v3[LINE_REC_LEN_V3] = +// type annot#1 , + {0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // 0x00 +//show length, +// order +//behind roads + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18 +// blue 2pt + 0x12, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, // 0x20 +// show line + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // 0x28 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x30 + 0x00}; + +char std_annot_linerec_header_v4[LINE_REC_LEN_V4] = +// type annot#1 , + {0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // 0x00 + + 0x00, 0x00, 0x00, 0x00, + +//show length, +// order +//behind roads + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +// blue 2pt + 0x12, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, +// show line + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00}; + +//struct parameters { +// Also need to include variable text length + line-points with these + +// These change with file version, so handle in code +int annot_rec_len[4]={57, 868, 124, 868}; +//int annot_head_len[4]={57, 48, 48, 48}; + +char * annot_type_name[4]={"Line", "Oval", "Textbox", "Circle"}; +//} tag_parameters; + +// constants for converting from MS Grid & Precision to latitude and longitude +// double magic1=182.044444444444; // = 2^16/360 +// double magic2=0x10000; + +/* +typedef struct annotationbuf +{ + int annot_num; + int flags; // bit fields in first byte + int unkn1; // normally 0 + int unkn2; // ? seems to have byte fields + int text_len; + // + 2*text_len bytes of text here + int fill_color; // seems to have byte fields. First byte is fill, other bytes are strange + int line_color; + int line_thickness; // 20 times the point-size + int arrow_type; // 00=none, 01=left, 02=right, 03=both + int unkn3; + int joinflag; // 0 line does not join, 1, joins. Not sure what large balues for non-lines mean - xscale? + char unkn4; // y-scale? + int num_points; // different meaning for non-lines +} structannotationbuf; +*/ + + +struct annot_rec * annot_rec_new() +{ + struct annot_rec * nw = (struct annot_rec *)xmalloc(sizeof(struct annot_rec)); + nw->type=-1; + nw->length=0; + nw->buf=NULL; + nw->annot_num = -1; + nw->text_length = 0; + nw->text = NULL; + nw->line_points=0; + nw->line_offset=0; + return nw; +} + +void annot_rec_delete(struct annot_rec * annot_rec) +{ + //int i; + if (annot_rec==NULL) + return; + //for(i=0; iline_points) + xfree(annot_rec->buf); + xfree(annot_rec->text); + xfree(annot_rec); +} + +struct annotations * annotations_new() +{ + struct annotations * nw = (struct annotations*)xmalloc(sizeof(struct annotations)); + nw->annot_list=NULL; + nw->header_buf=NULL; + nw->max_annot_num=0; + nw->num_annotations=0; + nw->read_recs_ok_flag=0; + nw->read_tail_ok_flag=0; + nw->stream_length=0; + nw->tail_buf_length=0; + nw->version=0; + return nw; +} + +void annotations_delete(struct annotations * annots) +{ + int i; + if (annots==NULL) + return; + + for (i=0; inum_annotations; i++) + annot_rec_delete(annots->annot_list[i]); + xfree(annots->annot_list); + xfree(annots->header_buf); + xfree(annots); +} + +struct gpxpt* gpx_get_point(char* buf) +// Convert the 12-byte location structure in annotations stream to GPS coordinates. +{ + struct gpxpt * pt = gpxpt_new(); + double x; + double y; + double z; + + if (buf==NULL) + { + printf("Trying to read line point from NULL\n"); + gpxpt_delete(pt); + return NULL; + } + + x= *(float *)(buf); + y= *(float *)(buf + 4); + z= *(float *)(buf + 8); + + //printf("gpx_get_point x=%f y=%f z=%f\n",x,y,z); + pt->lat = atan2(z,sqrt(pow(x,2)+ pow(y,2)))*180/M_PI; + pt->lon = atan2(y,x)*180/M_PI; + // 6378137 is earths equatorial radius in meters + // set elevation for curiosity, but dont enable it with pt->use_elevation + pt->elevation= (sqrt(pow(x,2)+ pow(y,2)+ pow(z,2))-1)*6378137; + return pt; +} + +struct annot_rec * read_annot_rec(FILE* annot_in_file, int version) +{ + int status; + int i; + int bit_flags=0; + int text_offset; + int text_len_offset; + int line_offset; + char* rec_type=NULL; + + struct annot_rec * rec = annot_rec_new(); + int head_len = 0; + switch (version) + { + case 3: + head_len = ANNOT_REC_HEAD_LEN; + text_len_offset = ANNOT_RECOS_TEXTLEN; + text_offset = ANNOT_RECOS_TEXT; + line_offset = 57; + break; + case 4: + head_len = ANNOT_REC_HEAD_LEN+4; + text_len_offset = ANNOT_RECOS_TEXTLEN+4; + text_offset = ANNOT_RECOS_TEXT+4; + line_offset = 57 + 4; + break; + default: + // FIXME version is passed as a param, should be handled there + printf("Unrecognised record format type %d, unable to process more annotations.\n", rec->type); + return NULL; + break; + } + + // ********************** + // Read the record header, up to begining of possible text + // ********************** + + rec->buf = (char*)xmalloc(head_len); + // This read can fail because I have miscalculated size or number of records + // So exit gracefully + status = readbytes(annot_in_file, rec->buf, head_len); + if (status!=head_len) + { + //FIXME +// gpx_write_file_trailer(gpx_out_file); + // exit(1) + // should do some cleaning up here + return rec; + } + + rec->type = *(int*)(rec->buf+ANNOT_RECOS_TYPE); + if (rec->type > 3 ) + { + printf("Unrecognised record type %d, unable to process more annotations\n", rec->type); + printbuf(rec->buf, head_len); + return NULL; + } + + rec->annot_num = *(int*)(rec->buf+ANNOT_RECOS_ANUM); + // FIXME kludge, fit into the framework + bit_flags = *(int*)(rec->buf + 8); + rec->text_length = *(int*)(rec->buf+text_len_offset); + rec->line_points=0; + if (rec->type == ANNOT_TYPE_LINE) + rec->line_points = *(int*)(rec->buf+head_len-4); + + // *************************** + // Calculate the record length + // *************************** + + rec->length = annot_rec_len[rec->type] + 2*rec->text_length + 12*rec->line_points; + if (version > 3) + rec->length += 4; + + // FIXME This is a kludge + if (opts.st_version_num>10) + { + if ( (rec->type == 1) || (rec->type == 4) ) + { + printf("Fudge: shortening 336 bytes from oval record length, but I dont know why.\n"); + (rec->length) -= 336; + } + } + + if (rec->type == ANNOT_TYPE_LINE) + rec->line_offset = line_offset; + + if (rec->type<4) + rec_type =annot_type_name[rec->type]; + else + rec_type=NULL; + + if (opts.verbose_flag > 4) + printf("Got annotation id %d, of type %d=%s, text length %d\n", + rec->annot_num, rec->type, rec_type, rec->text_length); + + // **************************** + // Read the rest of the record, from begining of possible text + // **************************** + + rec->buf = (char*)xrealloc(rec->buf, rec->length); + status = readbytes(annot_in_file, rec->buf+head_len, rec->length - head_len); + + if (status!=(rec->length - head_len)) + { + printf("Unable to read next part of annotation record - quiting\n"); + // fixme - we should stop processing annots but continue with rest + debug_pause(); + exit(1); + } + + if(rec->text_length>0) + { + rec->text=(char*)xmalloc(rec->text_length+1); + rec->text[rec->text_length]=0x0; + for (i=0;itext_length;i++) + rec->text[i]=rec->buf[text_offset + 2*i]; + str2ascii(rec->text); + } + + if (opts.verbose_flag > 1) + print_annot_rec(rec); + + if (opts.verbose_flag > 4) + { + printf("Recognised record with length %i\n",rec->length); + printbuf(rec->buf, rec->length); + } + + return rec; +} + +struct annotations * process_annotations_stream(char* annot_in_file_name) +{ + // Read the annotation file header + int i; + int status; + struct annot_rec * rec; + char* checkEOF; + int read_tail_buff=1; + FILE* annot_in_file=NULL; + struct annotations * annots = annotations_new(); + + annots->header_buf=(char*)xmalloc(ANNOT_FILE_HEAD_LEN); + + if ((annot_in_file = fopen(annot_in_file_name, "rb")) == NULL) + { + fprintf(stderr, "Quitting because I cannot open %s\n", annot_in_file_name); + debug_pause(); + exit(1); + } + + status=readbytes(annot_in_file, annots->header_buf, ANNOT_FILE_HEAD_LEN); + if (status!=ANNOT_FILE_HEAD_LEN) + { + printf("Cant make any more sense of annotations stream, continuing\n"); + return annots; + } + annots->stream_length += ANNOT_FILE_HEAD_LEN; + + for (i=1; i<8; i++) + if ( annots->header_buf[i] != std_annotfile_header[i] ) + printf("Nonstandard annotations file header, header[%i]=0x%x, normal value is 0x%x\n", + i, annots->header_buf[i], std_annotfile_header[i] ); + + annots->version = *(int*)(annots->header_buf+4); + annots->num_annotations = *(int*)(annots->header_buf+8); + + annots->annot_list = (struct annot_rec **)xmalloc( + (annots->num_annotations)*sizeof(struct annot_rec*)); + + if (opts.verbose_flag > 1) + { + printf("Annotations file header, version %d, indicates %d annotations in file\n", + annots->version, annots->num_annotations); + } + + if (opts.verbose_flag > 4) + { + printf("Dumping file header:\n"); + printbuf(annots->header_buf, ANNOT_FILE_HEAD_LEN); + } + + /* + ** Read all the annotation records + */ + annots->read_recs_ok_flag = 1; + for (i=0; i < annots->num_annotations; i++) + { + rec = read_annot_rec(annot_in_file, annots->version); + + // current version of explore annots is a bit childish +// if (opts.explore_flag) +// explore_annot(rec); + if (rec==NULL) + { + annots->read_recs_ok_flag = 0; + annots->num_annotations = i-1; + read_tail_buff=0; + break; + } + + annots->annot_list[i] = rec; + annots->max_annot_num = __max(annots->max_annot_num, rec->annot_num); + annots->stream_length += rec->length; + } + + // Check that we are at the end of annotation file + if (read_tail_buff) + { + checkEOF = xmalloc(4); + status=readbytes(annot_in_file, checkEOF, 4); + annots->stream_length += status; + if ( (status!=4) || (checkEOF[0]!=0) || (checkEOF[1]!=0) + || (checkEOF[2]!=0) || (checkEOF[3]!=0) || (getc(annot_in_file)!=EOF) ) + { + fprintf (stderr, "Did not finish reading annotation file at EOF\n"); + } + else + annots->read_tail_ok_flag=1; + xfree(checkEOF); + } + fclose(annot_in_file); + return annots; +} diff --git a/st2gpx/src/annotations.h b/st2gpx/src/annotations.h new file mode 100644 index 000000000..0fe4814fd --- /dev/null +++ b/st2gpx/src/annotations.h @@ -0,0 +1,181 @@ +/* + annotations.h + + Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format. + + Copyright (C) 2003 James Sherring, james_sherring@yahoo.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + + This app depends on istorage & istorage-make from Pabs (pabs3@zip.to) + and James Clark's Expat xml parser from http://www.libexpat.org/. + +*/ +#ifdef __cplusplus +extern "C" { +#endif + +#define ANNOT_FILE_HEAD_LEN 12 +// This needs to be long enough to get enough params to decide which record, +// but no biger than the shortest record +#define ANNOT_REC_HEAD_LEN 57 //19 + +#define ANNOT_TYPE_LINE 0 +#define ANNOT_TYPE_OVAL 1 +#define ANNOT_TYPE_TEXT 2 +#define ANNOT_TYPE_CIRCLE 3 + +#define REC_CLOSE_LEN 0 +// offsets for parameters in annotation recods +#define ANNOT_RECOS_TYPE 0 +#define ANNOT_RECOS_ANUM 4 +#define ANNOT_RECOS_TEXTLEN 20 +#define ANNOT_RECOS_TEXT 24 +#define ANNOT_RECOS_LINENUMPOINTS 53 +#define ANNOT_RECOS_LINEJOINFLAG 48 +#define ANNOT_RECOS_XSCALE 48 +#define ANNOT_RECOS_YSCALE 52 + +// + 12*NUM POINTS +#define LINE_REC_LEN_V3 57 +#define LINE_REC_LEN_V4 61 //??? + + +//#define ANNOT_TYPE_LINE 0 +//#define ANNOT_TYPE_OVAL 1 +//#define ANNOT_TYPE_TEXT 2 +//#define ANNOT_TYPE_CIRCLE 3 + +/* +typedef struct annotations_file_head +{ + // always 0x2d001234 + unsigned int uiunkn0; + // autoroute 2001: version=3 + // autoroute 2003: version=4 + unsigned int version; + // number of annotations in the stream + unsigned int c_annots; +} tag_annotations_file_head; + +typedef struct annotation_record_header +{ + // 0 = line + // 1 = Oval + // 2 = Textbox/Rectangle + // 3 = Circle + unsigned int type; + // 0x8 = show length + // 0x10 = order before roads + // (order defore other objects depends on file order (last highest) and obj type) + unsigned int bitflags; + int iunkn0; + int iunkn1; + // iunkn2 is only for version 10+ (9+?) + int iunkn2; + unsigned int text_len; + char text[]; + // 0 =black + // 12=blue + unsigned int fill_color; + // 0 = none + // 1 = fill + // + some other high-byte flags? + int fill_flag; + // 0 = black + // 12 = blue + // 0d = yellow + unsigned int line color; + // 20*point size + unsigned int line_width; + // 00=none, + // 01=left, + // 02=right, + // 03=both; + int arrow_type; + int iunkn3; + // 01 is a joined line: the first & last points are joined + // 00 is a line-type + int closed_flag; + char cunkn0; + // number of points in the line + char c_line_points; + struct point_rec[]; +} tag_annotation_header; + +struct annot_line_point +{ + float x; + float y; + float z; +} + +*/ + +typedef struct annot_rec +{ + // ANNOT_TYPE_ + int type; + int length; + char* buf; + int annot_num; + int text_length; + char* text; + int line_points; + // Pointer to the line-points data in buf, + // because it moves with different file formats. + int line_offset; +} tag_annot_rec; + +struct annot_rec * annot_rec_new(); +void annot_rec_delete(struct annot_rec * annot_rec); + +typedef struct annotations +{ + int num_annotations; + int max_annot_num; + char* header_buf; + struct annot_rec ** annot_list; + int tail_buf_length; + char read_recs_ok_flag; + char read_tail_ok_flag; + int stream_length; + // This is the annotations version number, as stored in the annotations stream + int version; +} tag_annotations; + +struct annotations * annotations_new(); +void annotations_delete(struct annotations * annots); +struct gpxpt* gpx_get_point(char* buf); + +extern char std_annotfile_header[ANNOT_FILE_HEAD_LEN]; +extern char std_annot_linerec_header_v3[LINE_REC_LEN_V3]; +extern char std_annot_linerec_header_v4[LINE_REC_LEN_V4]; + +//struct parameters { +// Also need to include variable text length + line-points with these +extern char* annot_type_name[4]; +extern char* gpxptypelabel[3]; +extern char * st_version[]; + +//} tag_parameters; + +struct annotations * process_annotations_stream(char* annot_in_file_name); + + +#ifdef __cplusplus +} +#endif diff --git a/st2gpx/src/bugs.txt b/st2gpx/src/bugs.txt new file mode 100644 index 000000000..9c737d600 --- /dev/null +++ b/st2gpx/src/bugs.txt @@ -0,0 +1,21 @@ +st2gpx known issues + + +Features: + + Depends on ADO2.5 + + Known to work with Autoroute 2001, + + Probably works with Autoroute 2002-3, Streets & Trips 2000-4, Mappoint 2000-4, + but not fully tested + + Overwrites output files without warning + + +Bugs: + + Problem with input name "steph's wedding.est", + but "steph's wedding.est" is ok (single space) + + with input file "Plesivec - Plešivec.gpx" we fail to open the gpx as input \ No newline at end of file diff --git a/st2gpx/src/build.txt b/st2gpx/src/build.txt new file mode 100644 index 000000000..a8830e18d --- /dev/null +++ b/st2gpx/src/build.txt @@ -0,0 +1,20 @@ +Build instructions: + +Build from VC++6 project. +Important notes: +* Use of 1-Byte struct alignment is required (rather than the MS default of 8) + due to the technique used here of overlaying a struct on an input buffer. +* Use of #import at the top of pushpins.cpp requires setting the Visual Studio paths + to include ado libraries (c:\program files\common files\system\ado for me) + or setting the path explictitly in the #include statement. +* Use of libexpat reqires a separate install of libexpat, and setting the + Visual Studio include and library paths to include libexpat. For me these are + D:\gpsbabel\Expat-1.95.7\Source\lib (for includes) and D:\gpsbabel\Expat-1.95.7\Libs + (for libs). + +* Where possible, I have disabled MS language extensions (proj setting/c++/customize). + Exceptions are: + getopt.c (ms extensions are enabled only for win32) + properties.c (I have some unitialised arrays in file structs, I should clean this up) + pushpins.c (lots...) + But**** I have used various ms specific lib functions: __max, _fullpath, diff --git a/st2gpx/src/contents.c b/st2gpx/src/contents.c new file mode 100644 index 000000000..ee6bf4aec --- /dev/null +++ b/st2gpx/src/contents.c @@ -0,0 +1,554 @@ +/* + contents.c + + Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format. + + Copyright (C) 2003 James Sherring, james_sherring@yahoo.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + + This app depends on istorage & istorage-make from Pabs (pabs3@zip.to) + and James Clark's Expat xml parser from http://www.libexpat.org/. + +*/ +#include +#include +#include + +#include "st2gpx.h" +#include "gpx.h" +#include "contents.h" +#include "annotations.h" + +char* buf2str(char* buf, int strlen) +// make a null-terminated string from a buf +{ + char*str=NULL; + if (strlen==0) + return NULL; + str=(char*)xmalloc(strlen+1); + memcpy(str, buf, strlen); + str[strlen]=0; + return str; +} + +struct contents * contents_new() +{ + struct contents * nw = (struct contents*)xmalloc(sizeof(struct contents)); + nw->fully_parsed_flag=0; + nw->buf_len=0; + nw->buf=NULL; + nw->f_conts0=NULL; + nw->f_conts_array=NULL; + nw->f_pcbtext0=NULL; + nw->f_text0=NULL; + nw->f_conts1=NULL; + nw->f_text1=NULL; + nw->f_conts2=NULL; + // conts2->count_strings strings. + // Strings are not nul-terminated, + // but they are prefixed with their length. + nw->list_f_pcbtext=NULL; + nw->list_f_text=NULL; + nw->f_conts3=NULL; + // the end part of the buffer that has not been interpreted. + nw->rest=NULL; + return nw; +} + +void contents_delete(struct contents * conts) +{ + xfree(conts->list_f_pcbtext); + xfree(conts->list_f_text); + xfree(conts->buf); + xfree(conts); +} + +void print_f_contents0(struct f_contents0 * conts) +{ + struct gpxpt* map_cent=NULL; + + printf("struct f_contents1:\n"); + printf("usunkn0=%d\n", conts->usunkn0); + printf("map_center_X=%f\n", conts->map_center_X); + printf("map_center_Y=%f\n", conts->map_center_Y); + printf("map_center_Z=%f\n", conts->map_center_Z); + printf("map_scale=%f\n", conts->map_scale); + printf("iunkn0=%d\n", conts->iunkn0); + printf("iunkn1=%d\n", conts->iunkn1); + printf("iunkn2=%d\n", conts->iunkn2); + printf("iunkn3=%d\n", conts->iunkn3); + printf("iunkn4=%d\n", conts->iunkn4); + printf("iunkn5=%d\n", conts->iunkn5); + printf("iunkn6=%d\n", conts->iunkn6); + printf("legend_or_directions=%d\n", conts->legend_or_directions); + printf("iunkn7=%d\n", conts->iunkn7); + printf("iunkn8=%d\n", conts->iunkn8); + printf("iunkn9=%d\n", conts->iunkn9); + printf("usunkn2=%d\n", conts->usunkn2); + printf("iunkn10=%d\n", conts->iunkn10); + printf("iunkn11=%d\n", conts->iunkn11); + debug_pause(); + printf("iunkn12=%d\n", conts->iunkn12); + printf("iunkn13=%d\n", conts->iunkn13); + printf("map_format_pannels=%d\n", conts->map_format_pannels); + printf("iunkn14=%d\n", conts->iunkn14); + printf("map_format_style=%d\n", conts->map_format_style); + printf("iunkn16=%d\n", conts->iunkn16); + printf("map_format_font_size=%d\n", conts->map_format_font_size); + + printf("usunkn4=%d\n", conts->usunkn4); + printf("section_len=%d\n", conts->section_len); + printf("usunkn5=%d\n", conts->usunkn5); + printf("array_len=%d\n", conts->array_len); + + map_cent = gpx_get_point((char*)(&conts->map_center_X)); + printf("Got map center %f %f with scale %f (km?).\n", + map_cent->lat, map_cent->lon, conts->map_scale); + gpxpt_delete(map_cent); + + printf("\n"); + printf("\n"); + debug_pause(); +} +/* contents_array + printf("usunkn6=%d\n", conts->usunkn6); + printf("usunkn7=%d\n", conts->usunkn7); + printf("usunkn8=%d\n", conts->usunkn8); + printf("usunkn9=%d\n", conts->usunkn9); + printf("LastSetId=%d\n", conts->LastSetId); + printf("iunkn18=%d\n", conts->iunkn18); + printf("usunkn10=%d\n", conts->usunkn10); + printf("iunkn19=%d\n", conts->iunkn19); + printf("usunkn11=%d\n", conts->usunkn11); + printf("cbText0=%d\n", conts->cbText0); +*/ + +void print_f_contents1(struct f_contents1 * conts) +{ + printf("struct f_contents1:\n"); + + printf("iunkn20=%d\n", conts->iunkn20); + printf("cbText1=%d\n", conts->cbText1); + + printf("\n"); + debug_pause(); +} + +void print_f_contents2(struct f_contents2 * conts) +{ + printf("struct f_contents1:\n"); + + printf("iunkn21=%d\n", conts->iunkn21); + printf("count_strings=%d\n", conts->count_strings); + + printf("\n"); + debug_pause(); +} + +void print_f_contents3(struct f_contents3 * conts) +{ + printf("struct f_contents3:\n"); + + printf("usunkn15=%d\n", conts->usunkn15); + printf("usunkn16=%d\n", conts->usunkn16); + printf("usunkn17=%d\n", conts->usunkn17); + printf("usunkn18=%d\n", conts->usunkn18); + printf("cbCountryText=%d\n", conts->cbCountryText); + + printf("\n"); + debug_pause(); +} + +struct contents * parse_contents_buffer(char* buf, unsigned int buf_len) +{ + struct contents * conts = contents_new(); + unsigned int buf_pos=0; + char* temp_str; + unsigned int i; + + conts->buf = buf; + conts->buf_len=buf_len; + + // ***************** + // Parse f_contents0 + // ***************** + + conts->f_conts0 = (struct f_contents0 *)(conts->buf); + buf_pos += sizeof(struct f_contents0); + if (buf_pos>(conts->buf_len)) + { + printf("Oops, ran out of buffer with conts0.\n"); + return conts; + } + if(opts.explore_flag) + print_f_contents0(conts->f_conts0); + + // ************************** + // Parse conts->f_conts_array + // ************************** + + conts->f_conts_array=(unsigned short *)(conts->buf + buf_pos); + buf_pos += conts->f_conts0->array_len; + if (buf_pos>(conts->buf_len)) + { + printf("Oops, ran out of buffer with conts array.\n"); + return conts; + } + if(opts.explore_flag) + { + printf("Dumping Contents array:\n"); + printbuf((char*)(conts->f_conts_array), conts->f_conts0->array_len); + + for(i=0; i< 3; i++) + printf("Array[%d]=%d - unknown meaning\n", i, conts->f_conts_array[i]); + + printf("n:=Array[3]=%d is number of user pushpin sets\n", (conts->f_conts_array)[3]); + +// for(i=0; i< (conts->f_conts_array[3]); i++) +// printf("Array[%d]=%d is SetId for user PushpinSet[%d] \n", +// 4+i, +// conts->f_conts_array[4+i], +// conts->f_conts_array[3] - i -1); + + for(i=0; i< (conts->f_conts_array[3]); i++) + printf("Array[4+n-(%d)]=%d is SetId for user PushpinSet[%d]\n", + i, conts->f_conts_array[3+(conts->f_conts_array[3])-i], i); + + for(i=0; (4 + (conts->f_conts_array[3] +i)) < (conts->f_conts0->array_len)/2 ; i++) + printf("Array[5+n+(%d)]=%d - unknown meaning\n", + i, conts->f_conts_array[4+(conts->f_conts_array[3])+i]); + + debug_pause(); + +// printf("Dumping Contents array tail:\n"); +// printbuf((char*)(conts->f_conts_array + 4 + conts->f_conts_array[3]), +// (conts->f_conts0->array_len)-2*(4 + conts->f_conts_array[3]) ); + } + + // ************************ + // Parse f_cbtext0, f_text0 + // ************************ + + conts->f_pcbtext0=(unsigned char*)((conts->buf)+buf_pos); + buf_pos += sizeof(char); + if (buf_pos>(conts->buf_len)) + { + printf("Oops, ran out of buffer with text0 size.\n"); + return conts; + } + + conts->f_text0=(conts->buf)+buf_pos; + buf_pos += *(conts->f_pcbtext0); + if (buf_pos>(conts->buf_len)) + { + printf("Oops, ran out of buffer with text0.\n"); + return conts; + } + // conts->f_cbtext0 is a *pointer* to text len + if(opts.explore_flag) + { + temp_str=buf2str(conts->f_text0, *(conts->f_pcbtext0)); + printf("Got Text0='%s'\n", temp_str); + xfree(temp_str); + temp_str=NULL; + } + + // ***************** + // Parse f_contents1 + // ***************** + + conts->f_conts1 = (struct f_contents1 *)(conts->buf+buf_pos); + buf_pos += sizeof(struct f_contents1); + if (buf_pos>(conts->buf_len)) + { + printf("Oops, ran out of buffer with conts1.\n"); + return conts; + } + if(opts.explore_flag) + print_f_contents1(conts->f_conts1); + + // ************* + // Parse f_text1 + // ************* + + conts->f_text1 = (conts->buf)+buf_pos; + buf_pos += conts->f_conts1->cbText1; + if (buf_pos>(conts->buf_len)) + { + printf("Oops, ran out of buffer with text1.\n"); + return conts; + } + if(opts.explore_flag) + { + temp_str=buf2str(conts->f_text1, conts->f_conts1->cbText1); + printf("Got Text1='%s'\n", temp_str); + xfree(temp_str); + temp_str=NULL; + } + + // ***************** + // Parse f_contents2 + // ***************** + + conts->f_conts2 = (struct f_contents2 *)((conts->buf)+buf_pos); + buf_pos += sizeof(struct f_contents2); + if (buf_pos>(conts->buf_len)) + { + printf("Oops, ran out of buffer with conts2.\n"); + return conts; + } + if(opts.explore_flag) + print_f_contents2(conts->f_conts2); + + // *************************************** + // Parse list_f_cbtext[] and list_f_text[] + // *************************************** + + conts->list_f_pcbtext=(unsigned char**)xmalloc((conts->f_conts2->count_strings)*sizeof(unsigned char*)); + conts->list_f_text=(char**)xmalloc((conts->f_conts2->count_strings)*sizeof(char*)); + // initialise just incase we dont make it through the parse loop + for(i=0; i<(conts->f_conts2->count_strings); i++) + { + conts->list_f_pcbtext[i]=NULL; + conts->list_f_text[i]=NULL; + } + for(i=0; i<(conts->f_conts2->count_strings); i++) + { + // list_f_cbtext[i] is a *pointer* to text len + conts->list_f_pcbtext[i]=(unsigned char*)(conts->buf+buf_pos); + buf_pos += sizeof(unsigned char); + if (buf_pos>(conts->buf_len)) + { + printf("Oops, ran out of buffer with text[%d] size.\n", i); + return conts; + } + conts->list_f_text[i]=(conts->buf)+buf_pos; + buf_pos += conts->list_f_pcbtext[i][0]; + if (buf_pos>(conts->buf_len)) + { + printf("Oops, ran out of buffer with text%d.\n", i); + return conts; + } + if(opts.explore_flag) + { + temp_str = buf2str(conts->list_f_text[i], *(conts->list_f_pcbtext[i])); + printf("Got list_text[%d]='%s'\n", i, temp_str); + xfree(temp_str); + } + } + + // ************************** + // Parse pusunkn0 and piunkn1 + // ************************** + + conts->pusunkn0 = (unsigned short*)(conts->buf+buf_pos); + + buf_pos += sizeof(unsigned short); + if (buf_pos>(conts->buf_len)) + { + printf("Oops, ran out of buffer with pusunkn0.\n"); + return conts; + } + if(opts.explore_flag) + printf("usunkn0=%d\n", *(conts->pusunkn0) ); + + if(*(conts->pusunkn0) == 1) + { + conts->piunkn1 = (int*)((conts->buf)+buf_pos); + buf_pos += sizeof(int); + if (buf_pos>(conts->buf_len)) + { + printf("Oops, ran out of buffer with piunkn1.\n"); + return conts; + } + if(opts.explore_flag) + printf("iunkn1=%d\n", *(conts->piunkn1) ); + } + + // ***************** + // Parse f_contents2 + // ***************** + + conts->f_conts3 = (struct f_contents3 *)(conts->buf+buf_pos); + buf_pos += sizeof(struct f_contents3); + if (buf_pos>(conts->buf_len)) + { + printf("Oops, ran out of buffer with conts3.\n"); + return conts; + } + if(opts.explore_flag) + print_f_contents3(conts->f_conts3); + + // ***************** + // Parse CountryText + // ***************** + + conts->CountryText = (conts->buf)+buf_pos; + buf_pos += conts->f_conts3->cbCountryText; + if (buf_pos>(conts->buf_len)) + { + printf("Oops, ran out of buffer with text[%d].\n", conts->f_conts2->count_strings); + return conts; + } + if(opts.explore_flag) + { + temp_str=buf2str(conts->CountryText, conts->f_conts3->cbCountryText); + if(opts.explore_flag) + printf("Got CountryText='%s'\n", temp_str); + xfree(temp_str); + temp_str=NULL; + } + + if (buf_pos == conts->buf_len) + conts->fully_parsed_flag=1; + else + { + printf("Unexpected %d bytes of contents buffer still remaining.\n", + (conts->buf_len)-buf_pos); + printbuf((conts->buf)+buf_pos, (conts->buf_len)-buf_pos); + } + + return conts; +} + +struct contents * read_contents(char* conts_file_name) +{ + FILE* conts_file=NULL; + const unsigned int max_conts_buf=1000; + int readbyte=0; + unsigned int buf_pos=0; + char* buf=(char*)xmalloc(max_conts_buf); + struct contents * conts=NULL; + + // **************************************** + // Read the Contents stream into the buffer + // **************************************** + + if ((conts_file = fopen(conts_file_name, "rb")) == NULL) + { + fprintf(stderr, "Cannot open property file %s\n", conts_file_name); + return NULL; + } + + if ((readbyte = getc(conts_file))!=EOF) + { + do { + buf[buf_pos]=(char)readbyte; + buf_pos++; + if (buf_pos>max_conts_buf-1) + { + printf("oops, I didn't allocate enough buffer space for contents...\n"); + break; + } + } while ((readbyte = getc(conts_file))!=EOF); + + } + fclose(conts_file); + + printf("Read %d bytes in contents stream %s\n", buf_pos, conts_file_name); + if (opts.verbose_flag>4) + { + printbuf(buf, buf_pos); + printf("Now trying to enterpret this data...\n"); + debug_pause(); + } + + conts = parse_contents_buffer(buf, buf_pos); + + debug_pause(); + return conts; +} + +struct contents * contents_insert_ppinset(struct contents * old_conts, unsigned short newSetId) +{ + // After inserting pushpins into UserData db, + // we need to update the Contents structure to include the new pushpin set + // in the list of objects to display. + // Otherwise the new pushpins will no be visible or editable. + struct contents * nw_conts=NULL; + char* nw_buf=NULL; + unsigned int nw_buf_len=0; + unsigned int insert_position=0; + unsigned int arraylen_os=0; + + if (old_conts==NULL) + { + printf("Contents buffer is empty???. The outut file will have a corrupted pushpin set.\n"); + return NULL; + } + + if (old_conts->fully_parsed_flag == 0) + { + printf("Warning - modifying a contents stream that is not fully parsed.\n"); + // Actually, we only need to have parsed as far as old_conts->f_conts_array, + // but best to be safe. + if(old_conts->CountryText !=NULL) + printf("...but I seem to have parsed enough to continue.\n"); + else + { + printf("I have not parsed enough to continue. The outut file will have a corrupted pushpin set.\n"); + return NULL; + } + } + + nw_buf_len = old_conts->buf_len + 2*sizeof(unsigned char); + nw_buf = (char *)xmalloc(nw_buf_len); + + // insert after f_conts_array[3], ie at f_conts_array+4 + insert_position = ((char*)(old_conts->f_conts_array+4)-(old_conts->buf)); + + memcpy(nw_buf, old_conts->buf, insert_position); + memcpy(nw_buf + insert_position, &newSetId, sizeof(unsigned short)); + memcpy(nw_buf + insert_position + sizeof(unsigned short), + old_conts->buf + insert_position, + old_conts->buf_len - insert_position); + + // set the size of the contents aray + arraylen_os = (char*)&(old_conts->f_conts0->array_len) - old_conts->buf; + *(nw_buf + arraylen_os) += sizeof(unsigned short); + + // increase the number of pushpin sets in f_conts_array[3] + *(nw_buf + insert_position - sizeof(unsigned short)) +=1; + + nw_conts=parse_contents_buffer(nw_buf, nw_buf_len); + + return nw_conts; +} + +void write_contents(struct contents * conts, char* conts_file_name) +{ + FILE* conts_out_file; + int status; + + //printf("Writing new Contents stream to %s\n", conts_file_name); + + if ((conts_out_file = fopen(conts_file_name, "wb")) == NULL) { + fprintf(stderr, "Cannot open %s\n", conts_file_name); + fflush(stdout); + debug_pause(); + exit(1); + } + + status = fwrite(conts->buf, conts->buf_len, 1, conts_out_file); + if (status != 1) + printf("expected to write %d, actually wrote %d\n", conts->buf_len, status*(conts->buf_len)); + else + printf("Wrote %d bytes to new contents stream in %s\n", conts->buf_len, conts_file_name); + + fclose(conts_out_file); + +} \ No newline at end of file diff --git a/st2gpx/src/contents.h b/st2gpx/src/contents.h new file mode 100644 index 000000000..3a3064281 --- /dev/null +++ b/st2gpx/src/contents.h @@ -0,0 +1,224 @@ +/* + contents.h + + Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format. + + Copyright (C) 2003 James Sherring, james_sherring@yahoo.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + + This app depends on istorage & istorage-make from Pabs (pabs3@zip.to) + and James Clark's Expat xml parser from http://www.libexpat.org/. + +*/ +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct f_contents0 +{ + // @ 00 + unsigned short usunkn0; // 0c 00 + float map_center_X; + float map_center_Y; + float map_center_Z; + // in km? + float map_scale; + // @ 12 + int iunkn0; // 00 00 00 00 + // next two are interesting when there are ppins imported from a file + // got 180213657 = ABDD799 + // and -1073143305 = C00921F7 + int iunkn1; + int iunkn2; + int iunkn3; // 20 03 00 00 + // @ 22 + int iunkn4; // 01 00 00 00 + int iunkn5; // 06 00 00 00 + int iunkn6; // c4 09 00 00 + // 0=legend/route directions if + // 1=no legend + // (related to iunkn13) + unsigned short legend_or_directions; // 00 00 / 01 00 + // @ 30 + int iunkn7; // 01 00 00 00 + int iunkn8; // 06 00 00 00 + int iunkn9; // e4 0c 00 00 for eur8, c4 09 00 00 for usa9 + unsigned short usunkn2; // 00 00 + int iunkn10; // 1 + // @ 42 + int iunkn11; // 06 00 00 00 + int iunkn12; // XX XX 00 00 + unsigned short iunkn13; // 00 00 + + // Does not seem to match these values... + //GeoPaneState Value Description + //geoPaneLegend 0 Legend is displayed + //geoPaneNearbyPlaces 2 Find Nearby Places pane is displayed + //geoPaneNone 3 Only the map is displayed + //geoPaneRoutePlanner 1 Route Planner pane is displayed + //geoPaneTerritory 4 Territory Manager pane is displayed + + // 0=no legend or show route directions ( iunkn6) + // 1=normal + // 2=route planner + // 4=find nearby places + int map_format_pannels; + // @ 50 + int iunkn14; // 1 0 4 0 + +// GeoMapStyle Value Description +// geoMapStyleData 2 Data map +// geoMapStylePolitical 4 Political map +// geoMapStyleRoad 0 Road map +// geoMapStyleRoadData 1 Road and data map +// geoMapStyleTerrain 3 Terrain map + + // 0 = Road + // 3 = Terrain + // 4 = Political + int map_format_style; + int iunkn16; // 1 0 4 0 + // 0-4, + // 0=largest + // 4=smallest + int map_format_font_size; // 03 00 00 00 + // @ 60 + unsigned short usunkn4; //03 00 + //length of section from here until end of EUR/USA string + int section_len; + unsigned short usunkn5; // 03 00 + // array_len = 0x14 + 2*num ppin sets + // if array_len=0x14, str1@81. if array_len=0x16 str1@83 + unsigned int array_len; // xx 00 00 00 (14/16) +} tag_f_contents0; + +/* +typedef struct f_contents_array +{ + unsigned short usunkn6; // 03 00 + unsigned short usunkn7; // 02/01 00 + // @ 70 + unsigned short usunkn8; // 00 00 + // number of user ppin sets + unsigned short usunkn9; // 00/01 00 (0 for empty, 1 for ppins?) + // from UserData/GEODB_LastId/LastSetId + // note the size mismatch: short/long + unsigned short LastSetId; + unsigned short usunkn9_1; // 0 + unsigned short usunkn9_2; // 0 + unsigned short usunkn10; // 0 + unsigned short usunkn10_1; // 0 + unsigned short usunkn10_2; // 0 + int iunkn19; // 3 + // @ 80 + unsigned short usunkn11; // 0 +} tag_f_contents_array; +*/ + +// + unsigned char cbText0; +// + cbText0 bytes of text + +// @ 8b + +typedef struct f_contents1 +{ + int iunkn20; // 00 00 00 00/ff ff ff ff + unsigned char cbText1; +} tag_f_contents1; + +// + cbText1 bytes of text +// @ 98 +typedef struct f_contents2 +{ + int iunkn21; // ff ff ff ff + // This is a count of strings before contents3 + unsigned short count_strings; // 3 +} tag_f_contents2; + +// unsigned char cbText2; +// + cbText2 bytes of text +// @ a6 +// + unsigned char cbText3 +// + cbText3 bytes of text +// @ ae +// + optional ? unsigned char cbText4 +// + optional ? cbText4 bytes of text +// @ b7 + +//+ unsigned short usunkn14; +// + int (if usunkn14) + +typedef struct f_contents3 +{ + unsigned short usunkn15; + unsigned short usunkn16; + unsigned short usunkn17; + unsigned short usunkn18; + // FIXME + an extra short for usa9, + 2 extra shorts for usa10 + unsigned char cbCountryText; +} tag_f_contents3; + +// + cbText5 bytes of text: USA/EUR + +// more for USA9 +// + int +// + unsigned char cbText6 +// + cbText6 bytes of text +// + unsigned char cbText7 +// + cbText7 bytes of text : path to html: html export file? +// + 0x40 bytes + + +typedef struct contents +{ + int fully_parsed_flag; + unsigned int buf_len; + // The data as read from the contents stream. + char* buf; + struct f_contents0 * f_conts0; + unsigned short * f_conts_array; + unsigned char * f_pcbtext0; + char* f_text0; + struct f_contents1 * f_conts1; + char* f_text1; + struct f_contents2 * f_conts2; + // Lengths for conts2->count_strings number of strings. + // Note that this is array of *pointers* to string-length + unsigned char ** list_f_pcbtext; + // conts2->count_strings number of strings. + // Strings are not null-terminated, + // but they are prefixed with their length. + char ** list_f_text; + // Normally 0, sometimes 1 + unsigned short * pusunkn0; + // Only when usunkn0=1 ??? + int * piunkn1; + struct f_contents3 * f_conts3; + char * CountryText; + // The end part of the buffer that has not been interpreted. + char* rest; +} tag_contents; + +struct contents * read_contents(char* conts_file_name); +struct contents * contents_insert_ppinset(struct contents * old_conts, unsigned short newSetId); +void write_contents(struct contents * conts, char* conts_file_name); +void contents_delete(struct contents * conts); + +#ifdef __cplusplus +} +#endif + diff --git a/st2gpx/src/debug.c b/st2gpx/src/debug.c new file mode 100644 index 000000000..e1cf06f5a --- /dev/null +++ b/st2gpx/src/debug.c @@ -0,0 +1,589 @@ +/* + debug.c + + Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format. + + Copyright (C) 2003 James Sherring, james_sherring@yahoo.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + + This app depends on istorage & istorage-make from Pabs (pabs3@zip.to) + and James Clark's Expat xml parser from http://www.libexpat.org/. + +*/ +#include +#include +#include + +#include "gpx.h" +#include "st2gpx.h" +#include "getopt.h" +#include "properties.h" +#include "pushpins.h" +#include "ppinutil.h" +#include "annotations.h" +#include "journey.h" + +void debug_pause() +{ + char c; + if (opts.debug_wait_flag) + { + fprintf(stderr, "Hit Enter key to continue\n"); + c=getchar(); + // a way to stop pausing + if (c=='q') + opts.debug_wait_flag=0; + } +} + +int fixhex(char c) +{ +// gcc (version?) does not print single byte hex values properly +// eg 0xe3 prints as 0xFFFFFFE3 +// this is only a problem for values above 0x80 +// Or maybe that is the proper handling of unsigned? +// Aaaahhh. I should use %u for printing unsigned... but the hex problem is still there + if(c & 0x80) + { + return ((int)c-0xFFFFFF00); + } else + return c; +} + +void printbuf(char* buf, int len) +{ +// unsigned i; + int i; + printf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n"); + printf(" -----------------------------------------------"); + for(i=0; ilat, pt->lon, pt->elevation); + gpxpt_delete(pt); + } + printf("\n\n"); +} + +void printpointsbuf(char* buf, int len) +{ +// unsigned i; +// unsigned j; + int i; + int j; + printf(" 0 1 2 3 4 5 6 7 8 9 A B\n"); + printf(" -----------------------------------"); + for(i=0; ilat, pt->lon, pt->elevation); + gpxpt_delete(pt); + fflush(stdout); + } + printf("\n\n"); +} + +void printnzbuf(char* buf, int len) +{ +// print non-zero values in the buffer +// unsigned i; + int i; + for(i=0; ibuf, ANNOT_RECOS_TEXT); + memcpy(header+ANNOT_RECOS_TEXT+2*rec->text_length, rec->buf, + ANNOT_REC_HEAD_LEN-ANNOT_RECOS_TEXT); + + tail = rec->buf+ANNOT_REC_HEAD_LEN+2*rec->text_length; + taillength = rec->length - ANNOT_REC_HEAD_LEN+2*rec->text_length; + + printf("Record buffer\n", annot_type_name[rec->type]); + printbuf(rec->buf, rec->length); + printf("Record high buffer\n", annot_type_name[rec->type]); + printbufhigh(rec->buf, rec->length); + printf("Record wide header:\n", annot_type_name[rec->type]); + printbufwide(header, ANNOT_REC_HEAD_LEN); + printf("Record tail:\n"); + printbuf(tail, taillength); + printf("Record wide tail:\n"); + printbufwide(tail, taillength); + printf("Record tail as floats:\n"); + printbufasfloat(tail, taillength); + printf("Record tail as points:\n"); + printbufaspoints(tail, taillength); +// if (rec->type == ANNOT_TYPE_TEXT) +// { + //printfloatbuf((float*)(tail+3), taillength/4 -1); +// } +// else if (rec->type == ANNOT_TYPE_OVAL ) +// printfloatbuf((float*)(tail+3), taillength/4 -1); +// else if (rec->type == ANNOT_TYPE_CIRCLE )) +// printfloatbuf((float*)(tail+3), taillength/4 -1); + xfree(header); +} + +void print_f_jour_header(struct f_jour_header * head) +{ + printf("struct f_jour_header:\n"); + printf("iunkn0 %x=%d\n", head->iunkn0, head->iunkn0); + printf("iunkn1 %x=%d\n", head->iunkn1, head->iunkn1); + printf("iunkn2 %x=%d\n", head->iunkn2, head->iunkn2); + printf("iunkn3 %x=%d\n", head->iunkn3, head->iunkn3); + printf("cpoints %x=%d\n", head->cpoints, head->cpoints); + printf("iunkn4 %x=%d\n", head->iunkn4, head->iunkn4); + printf("iunkn5 %x=%d\n", head->iunkn5, head->iunkn5); + printf("iunkn6 %x=%d\n", head->iunkn6, head->iunkn6); +} + +void print_f_jour_pt_head(struct f_jour_pt_head * pt_head) +{ +// double x; + printf("struct f_jour_pt_head:\n"); + printf("UdId %d\n", pt_head->UdId); + printf("stop_dur_secs %d\n", pt_head->stop_dur_secs); + printf("iunkn0 %#x=%d\n", pt_head->iunkn0, pt_head->iunkn0); + printf("sched_arrive_flag %d\n", pt_head->sched_arrive_flag); + printf("sched_depart_flag %d\n", pt_head->sched_depart_flag); + printf("arrive_time_secs %d\n", pt_head->arrive_time_secs); + printf("depart_time_secs %d\n", pt_head->depart_time_secs); + printf("iunkn1 %#x=%d\n", pt_head->iunkn1, pt_head->iunkn1); +// x = pt_head->unkn_scaled_lon; +// x = x*360/0x10000; +// x = x/0x10000; + printf("scaled_lon %d gives lon %f\n", + pt_head->scaled_lon, scaled2deg(pt_head->scaled_lon)); +// x = (pt_head->unkn_scaled_lat*360/0x10000); +// x = x/0x10000; + printf("scaled_lat %d gives lat %f\n", + pt_head->scaled_lat, scaled2deg(pt_head->scaled_lat)); + printf("cbtext1 %d\n",pt_head->cbtext1); + printbuf((char*)pt_head, sizeof(struct f_jour_pt_head)); +} + +void print_f_jour_pt_tail(struct f_jour_pt_tail * pt_tail) +{ + printf("struct f_jour_pt_tail: \n"); + printf("route_rd_pref %x\n",pt_tail->route_rd_pref); + printf("iunkn0 %x=%d\n", pt_tail->iunkn0, pt_tail->iunkn0); + printf("iunkn1 %x=%d\n", pt_tail->iunkn1, pt_tail->iunkn1); + printf("iunkn2 %x=%d\n", pt_tail->iunkn2, pt_tail->iunkn2); + printf("iunkn3 %x=%d\n", pt_tail->iunkn3, pt_tail->iunkn3); + printf("road_id %x=%d\n", pt_tail->road_id, pt_tail->road_id); + printf("dist_along_rd_frac %lf \n", pt_tail->dist_along_rd_frac); + + printf("rd_arrive_sc_lat %d gives lat %f\n", + pt_tail->rd_arrive_sc_lat, scaled2deg(pt_tail->rd_arrive_sc_lat)); + + printf("rd_arrive_sc_lon %d gives lat %f\n", + pt_tail->rd_arrive_sc_lon, scaled2deg(pt_tail->rd_arrive_sc_lon)); + + printf("rd_depart_sc_lat %d gives lat %f\n", + pt_tail->rd_depart_sc_lat, scaled2deg(pt_tail->rd_depart_sc_lat)); + + printf("rd_depart_sc_lon %d gives lat %f\n", + pt_tail->rd_depart_sc_lon, scaled2deg(pt_tail->rd_depart_sc_lon)); + + printf("iunkn8 %x=%d\n", pt_tail->iunkn8, pt_tail->iunkn8); + printf("iunkn9 %x=%d\n", pt_tail->iunkn9, pt_tail->iunkn9); + printf("iunkn10 %x=%d\n", pt_tail->iunkn10, pt_tail->iunkn10); + printf("iunkn11 %x=%d\n", pt_tail->iunkn11, pt_tail->iunkn11); + printf("iunkn12 %x=%d\n", pt_tail->iunkn12, pt_tail->iunkn12); + printf("iunkn13 %x=%d\n", pt_tail->iunkn13, pt_tail->iunkn13); + printf("iunkn14 %x=%d\n", pt_tail->iunkn14, pt_tail->iunkn14); + + printbuf((char*)pt_tail, sizeof(struct f_jour_pt_tail)); +} + +void print_f_jour_opts(struct f_jour_opts * jopts) +{ + printf("struct f_jour_opts:\n"); + + printf("siunkn0 %d\n", jopts->siunkn0); + printf("funkn0 %f\n", jopts->funkn0); + printf("toll_rd_pref %lf\n", jopts->toll_rd_pref); + printf("motorway_pref %lf\n", jopts->motorway_pref); + printf("major_rd_pref %lf\n", jopts->major_rd_pref); + printf("minor_rd_pref %lf\n", jopts->minor_rd_pref); + printf("ferry_pref %lf\n", jopts->ferry_pref); + printf("iunkn0 %d\n", jopts->iunkn0); + printf("iunkn1 %d\n", jopts->iunkn1); + printf("iunkn2 %d\n", jopts->iunkn2); + printf("fuel_price %lf\n", jopts->fuel_price); + printf("iunkn3 %d\n", jopts->iunkn3); + printf("fuel_price_unit %d\n", jopts->fuel_price_unit); + printf("iunkn4 %d\n", jopts->iunkn4); + printf("tank_capacity %lf\n", jopts->tank_capacity); + printf("tank_capacity_units %d\n", jopts->tank_capacity_units); + printf("tank_start_level %lf\n", jopts->tank_start_level); + printf("tank_warn_level %lf\n", jopts->tank_warn_level); + printf("iunkn5 %d\n", jopts->iunkn5); + printf("fuel_use_city %lf\n", jopts->fuel_use_city); + printf("fuel_use_city_unit %d\n", jopts->fuel_use_city_unit); + printf("iunkn6 %d\n", jopts->iunkn6); + printf("fuel_use_mway %lf\n", jopts->fuel_use_mway); + printf("fuel_use_mway_unit %d\n", jopts->fuel_use_mway_unit); + printf("iunkn7 %d\n", jopts->iunkn7); + printf("mway_speed %f\n", jopts->mway_speed); + printf("mway_speed_unit %d\n", jopts->mway_speed_unit); + printf("iunkn9 %d\n", jopts->iunkn9); + printf("lim_acc_speed %f\n", jopts->lim_acc_speed); + printf("lim_acc_speed_unit %d\n", jopts->lim_acc_speed_unit); + printf("iunkn11 %d\n", jopts->iunkn11); + printf("maj_rd_speed %f\n", jopts->maj_rd_speed); + printf("maj_rd_speed_unit %d\n", jopts->maj_rd_speed_unit); + printf("iunkn13 %d\n", jopts->iunkn13); + printf("min_rd_speed %f\n", jopts->min_rd_speed); + printf("min_rd_speed_unit %d\n", jopts->min_rd_speed_unit); + printf("iunkn15 %d\n", jopts->iunkn15); + printf("street_speed %f\n", jopts->street_speed); + printf("street_speed_unit %d\n", jopts->street_speed_unit); + printf("iunkn17 %d\n", jopts->iunkn17); + printf("iunkn18 %d\n", jopts->iunkn18); + printf("funkn1 %f\n", jopts->funkn1); + printf("iunkn19 %d\n", jopts->iunkn19); + printf("iunkn20 %d\n", jopts->iunkn20); + printf("iunkn21 %d\n", jopts->iunkn21); + printf("funkn2 %f\n", jopts->funkn2); + printf("iunkn22 %d\n", jopts->iunkn22); + printf("iunkn23 %d\n", jopts->iunkn23); + printf("iunkn24 %d\n", jopts->iunkn24); + printf("funkn3 %f\n", jopts->funkn3); + printf("iunkn25 %d\n", jopts->iunkn25); + printf("iunkn26 %d\n", jopts->iunkn26); + printf("iunkn27 %d\n", jopts->iunkn27); + printf("funkn4 %f\n", jopts->funkn4); + printf("iunkn28 %d\n", jopts->iunkn28); + printf("iunkn29 %d\n", jopts->iunkn29); + printf("iunkn30 %d\n", jopts->iunkn30); + printf("funkn5 %f\n", jopts->funkn5); + printf("iunkn31 %d\n", jopts->iunkn31); + printf("iunkn32 %d\n", jopts->iunkn32); + printf("iunkn33 %d\n", jopts->iunkn33); + printf("start_drv_hr %d\n", jopts->start_drv_hr); + printf("start_drv_min %d\n", jopts->start_drv_min); + printf("iunkn34 %d\n", jopts->iunkn34); + printf("end_drv_hr %d\n", jopts->end_drv_hr); + printf("end_drv_min %d\n", jopts->end_drv_min); + printf("fuel_warn_flag %d\n", jopts->fuel_warn_flag); + printf("iunkn35 %d\n", jopts->iunkn35); + printf("fuel_fixed_rate_flag %d\n", jopts->fuel_fixed_rate_flag); + printf("iunkn36 %d\n", jopts->iunkn36); + printf("fuel_cost_dist %d\n", jopts->fuel_cost_dist); + printf("route_flex_secs %d\n", jopts->route_flex_secs); + printf("iunkn37 %d\n", jopts->iunkn37); + printf("rest_flag %d\n", jopts->rest_flag); + printf("rest_dur_secs %d\n", jopts->rest_dur_secs); + printf("rest_interval_secs %d\n", jopts->rest_interval_secs); + + printbuf((char*)jopts, sizeof(struct f_jour_opts)); + printf("\n"); +} + +void print_f_jour_opts_EUR_8(struct f_jour_opts_EUR_8 * jopts) +{ + printf("struct f_jour_opts_EUR_8:\n"); + + printf("iunkn38 %d\n", jopts->iunkn38); + printf("iunkn39 %d\n", jopts->iunkn39); + printf("iunkn40 %d\n", jopts->iunkn40); + printf("iunkn41 %d\n", jopts->iunkn41); + printf("iunkn42 %d\n", jopts->iunkn42); + printf("siunkn1 %d\n", jopts->siunkn1); + printf("route_show_tm %d\n", jopts->route_show_tm); + printf("route_show_dist %d\n", jopts->route_show_dist); + printf("route_show_inst %d\n", jopts->route_show_inst); + printf("route_show_for %d\n", jopts->route_show_for); + printf("route_show_to %d\n", jopts->route_show_to); + printf("route_show_font_size %d\n", jopts->route_show_font_size); + printf("iunkn43 %d\n", jopts->iunkn43); + printf("iunkn44 %d\n", jopts->iunkn44); + printf("count_avoid_regions %d\n", jopts->count_avoid_regions); + + printbuf((char*)jopts, sizeof(struct f_jour_opts_EUR_8)); + printf("\n"); +} + +void print_f_jour_opts_EUR_10(struct f_jour_opts_EUR_10 * jopts) +{ + printf("struct f_jour_opts_EUR_10:\n"); + + printf("iunkn38 %d\n", jopts->iunkn38); + printf("iunkn39 %d\n", jopts->iunkn39); + printf("iunkn40 %d\n", jopts->iunkn40); + printf("iunkn41 %d\n", jopts->iunkn41); + printf("iunkn41 %d\n", jopts->iunkn42); + printf("count_avoid_regions %d\n", jopts->count_avoid_regions); + + printbuf((char*)jopts, sizeof(struct f_jour_opts_EUR_10)); + printf("\n"); +} + +void print_f_jour_opts_USA_8(struct f_jour_opts_USA_8 * jopts) +{ + printf("struct f_jour_opts_USA_8:\n"); + + printf("iunkn38 %d\n", jopts->iunkn38); + printf("iunkn39 %d\n", jopts->iunkn39); + printf("iunkn40 %d\n", jopts->iunkn40); + printf("iunkn41 %d\n", jopts->iunkn41); + printf("iunkn42 %d\n", jopts->iunkn42); + printf("siunkn1 %d\n", jopts->siunkn1); + printf("iunkn43 %d\n", jopts->iunkn43); + printf("iunkn44 %d\n", jopts->iunkn44); + printf("iunkn45 %d\n", jopts->iunkn45); + printf("iunkn46 %d\n", jopts->iunkn46); + printf("iunkn47 %d\n", jopts->iunkn47); + printf("iunkn48 %d\n", jopts->iunkn48); + printf("iunkn49 %d\n", jopts->iunkn49); + printf("count_avoid_regions %d\n", jopts->count_avoid_regions); + + printbuf((char*)jopts, sizeof(struct f_jour_opts_USA_8)); + printf("\n"); +} + +void print_f_jour_opts_USA_10(struct f_jour_opts_USA_10 * jopts) +{ + printf("struct f_jour_opts_USA_10:\n"); + + printf("iunkn38 %d\n", jopts->iunkn38); + printf("iunkn39 %d\n", jopts->iunkn39); + printf("iunkn40 %d\n", jopts->iunkn40); + printf("iunkn41 %d\n", jopts->iunkn41); + printf("iunkn42 %d\n", jopts->iunkn42); + printf("siunkn1 %d\n", jopts->siunkn1); + printf("iunkn43 %d\n", jopts->iunkn43); + printf("iunkn44 %d\n", jopts->iunkn44); + printf("count_avoid_regions %d\n", jopts->count_avoid_regions); + + printbuf((char*)jopts, sizeof(struct f_jour_opts_USA_10)); + printf("\n"); +} + +void print_f_jour_avoid(struct f_jour_avoid * avoid) +{ + struct gpxpt * gpt = gpx_get_point((char*)avoid); + struct point pt; + printf("struct f_jour_avoid:\n"); + + printf("x %f\n", avoid->x); + printf("y %f\n", avoid->y); + printf("z %f\n", avoid->z); + printf("iunkn0 %d\n", avoid->iunkn0); + printf("iunkn1 %d\n", avoid->iunkn1); + printf("iunkn2 %d\n", avoid->iunkn2); + printf("iunkn3 %d\n", avoid->iunkn3); + printf("iunkn4 %d\n", avoid->iunkn4); + printf("iunkn5 %d\n", avoid->iunkn5); + printf("annot_num %d\n", avoid->annot_num); + printf("x,y,z give lat %f and lon %f\n", gpt->lat, gpt->lon); + + pt = grid2latlon(avoid->iunkn1, avoid->iunkn2); + printf("iunkn1, lunkn2 as grid, precision give lat %f and lon %f\n", pt.lat, pt.lon); + pt = grid2latlon(avoid->iunkn2, avoid->iunkn3); + printf("iunkn2, lunkn3 as grid, precision give lat %f and lon %f\n", pt.lat, pt.lon); + pt = grid2latlon(avoid->iunkn3, avoid->iunkn4); + printf("iunkn3, lunkn4 as grid, precision give lat %f and lon %f\n", pt.lat, pt.lon); + + printbuf((char*)avoid, sizeof(struct f_jour_avoid)); + printf("\n"); +} + +void print_f_jour_trailer(struct f_jour_trailer * trailer) +{ + printf("struct f_jour_trailer:\n"); + + printf("iunkn0 %d\n", trailer->iunkn0); + printf("iunkn1 %d\n", trailer->iunkn1); + + printbuf((char*)trailer, sizeof(struct f_jour_trailer)); + printf("\n"); +} + +void print_annot_rec(struct annot_rec * rec) +{ + int bit_flags = *(int*)(rec->buf + 8); + char* rec_type = NULL; + + if (rec->type<4) + rec_type =annot_type_name[rec->type]; + + printf("Got annotation id %d, of type %s, %d line points", + rec->annot_num, rec_type, rec->line_points); + if(rec->text !=NULL) + printf(" and text '%s'", rec->text); + printf("\n"); + if (opts.verbose_flag > 4) + printf("(type=%d) text length %d, bitflags %#x buf length %d\n", + rec->type, rec->text_length, bit_flags, rec->length); +} + +void print_annotations(struct annotations * annots) +{ + int i; + // This is only the main stuff + printf("Annotations list, version=%d, num_annotations=%d, max_annot_num=%d, stream_length=%d\n", + annots->version, annots->num_annotations, + annots->max_annot_num, annots->stream_length); + + for(i=0; inum_annotations; i++) + print_annot_rec(annots->annot_list[i]); +} + +void debug_show_sizes() +{ + printf("sze of struct annot_rec is %d \n", sizeof(struct annot_rec)); + printf("sze of struct annotations is %d \n", sizeof(struct annotations)); + printf("sze of struct dictionary is %d \n", sizeof(struct dictionary)); +// printf("sze of struct FORMATIDOFFSET is %d \n", sizeof(struct FORMATIDOFFSET)); + printf("sze of struct gpx_data is %d \n", sizeof(struct gpx_data)); + printf("sze of struct gpxpt is %d \n", sizeof(struct gpxpt)); + printf("sze of struct gpxrte is %d \n", sizeof(struct gpxrte)); + printf("sze of struct gpxtrk is %d \n", sizeof(struct gpxtrk)); + printf("sze of struct jour_header is %d \n", sizeof(struct f_jour_header)); + printf("sze of struct jour_pt_head is %d \n", sizeof(struct f_jour_pt_head)); + printf("sze of struct jour_pt_mid is %d \n", sizeof(struct f_jour_pt_mid)); + printf("sze of struct jour_pt_tail is %d \n", sizeof(struct f_jour_pt_tail)); + printf("sze of struct jour_rtept_rec is %d \n", sizeof(struct jour_rtept)); +// printf("sze of struct jour_trailer_EUR_8 is %d \n", sizeof(struct jour_opts_EUR_8)); + printf("sze of struct jour_trailer_EUR_8 is %d \n", sizeof(struct f_jour_avoid)); +// printf("sze of struct jour_trailer_EUR_8 is %d \n", sizeof(struct jour_trailer_EUR_8)); + + debug_pause(); + + printf("sze of struct journey is %d \n", sizeof(struct journey)); + printf("sze of struct grid_point is %d \n", sizeof(struct grid_point)); + printf("sze of struct ole_property is %d \n", sizeof(struct ole_property)); + printf("sze of struct ole_property_set is %d \n", sizeof(struct ole_property_set)); + printf("sze of struct option is %d \n", sizeof(struct option)); + printf("sze of struct point is %d \n", sizeof(struct point)); +// printf("sze of struct PROPERTYIDOFFSET is %d \n", sizeof(struct PROPERTYIDOFFSET)); +// printf("sze of struct PROPERTYSETHEADER is %d \n", sizeof(struct PROPERTYSETHEADER)); + printf("sze of struct pushpin is %d \n", sizeof(struct pushpin)); + printf("sze of struct pushpin_safelist is %d \n", sizeof(struct pushpin_safelist)); + printf("sze of struct pushpinset is %d \n", sizeof(struct pushpinset)); +// printf("sze of struct SERIALIZEDPROPERTYVALUE is %d \n", sizeof(struct SERIALIZEDPROPERTYVALUE)); + printf("sze of struct st2gpx_options is %d \n", sizeof(struct st2gpx_options)); +// printf("sze of struct tagPROPERTYSECTIONHEADER is %d \n", sizeof(struct tagPROPERTYSECTIONHEADER)); +} diff --git a/st2gpx/src/gpx.h b/st2gpx/src/gpx.h new file mode 100644 index 000000000..107ddb6d2 --- /dev/null +++ b/st2gpx/src/gpx.h @@ -0,0 +1,109 @@ +/* + gpx.h + + Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format. + + Copyright (C) 2003 James Sherring, james_sherring@yahoo.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + + This app depends on istorage & istorage-make from Pabs (pabs3@zip.to) + and James Clark's Expat xml parser from http://www.libexpat.org/. + +*/ +#ifdef __cplusplus +extern "C" { +#endif + +#define GPX_ELEM_TYPE_WPT 1 +#define GPX_ELEM_TYPE_RTE 2 +#define GPX_ELEM_TYPE_RTEPT 3 +#define GPX_ELEM_TYPE_TRK 4 +#define GPX_ELEM_TYPE_TRKSEG 5 +#define GPX_ELEM_TYPE_TRKPT 6 + +#define GPX_ELEM_TYPE_NAME 7 +#define GPX_ELEM_TYPE_DESC 8 +#define GPX_ELEM_TYPE_SRC 9 + +typedef struct gpxpt +{ + double lat; + double lon; + double elevation; + char use_elevation; + char * name; + char * desc; + // more later +} tag_gpxpt; + +struct gpxpt * gpxpt_new(); +void gpxpt_delete(struct gpxpt * pt); +struct gpxpt * gpxpt_copy(struct gpxpt * otherpt); + +typedef struct gpxrte +{ + char* name; + struct gpxpt** rtept_list; + int rtept_list_count; +} tag_gpxrte; + +struct gpxrte * gpxrte_new(); +void gpxrte_delete(struct gpxrte * rte); + +typedef struct gpxtrk +{ + struct gpxpt** trkpt_list; + int trkpt_list_count; +} tag_gpxtrk; + +struct gpxtrk * gpxtrk_new(); +void gpxtrk_delete(struct gpxtrk * trk); + +typedef struct gpx_data +{ + char* data_source_name; + struct gpxpt ** wpt_list; + int wpt_list_count; + struct gpxrte ** rte_list; + int rte_list_count; + struct gpxtrk ** trk_list; + int trk_list_count; +} tag_gpx_data; + +struct gpx_data * gpx_data_new(); +void gpx_data_delete(struct gpx_data * data); + +struct gpxpt * find_matching_wpt(struct gpx_data * dat, char* name); + +struct gpx_data * process_gpx_in_file(char* gpx_in_file_name); +void print_gpx_data(struct gpx_data * all_data); + +// FIXME is this the correct way to forward define these? +#ifndef __cplusplus +extern struct pushpin_safelist; +extern struct journey; +extern struct annotations; +#endif // __cplusplus + +void gpx_write_all(char* gpx_out_file_name, + struct pushpin_safelist *ppplist, + struct journey * jour, + struct annotations * annots); + +#ifdef __cplusplus +} +#endif diff --git a/st2gpx/src/history.txt b/st2gpx/src/history.txt new file mode 100644 index 000000000..d5e0eb6bf --- /dev/null +++ b/st2gpx/src/history.txt @@ -0,0 +1,31 @@ +History: + +This app started out as ansi C using gcc as an app to explore the .axe file format, +and with the intention of fitting into the GPSBabel ansi C requirement. + +The pushpin data (UserData) required MS Jet libraries, initially this was done +with ADO in VB, then in C++ using MS #import. Note that the ADO type libraries +do not support C via #import, and I was not game to even try direct OLE access to the +ADO libraries via COM. + +So now there is an ugly mix of C/C++ in an app that grew organically rather than being designed. +It probably could be implemented a lot cleaner in c++ and with some inteligent use of streams +etc. + +Yeah, ok, I am just an amateur at this... + +18-10-2003 look mum! I can open an axe files into OLE storage streams using various tools. +21-10-2003 annotations stream dump +27-10-2003 journey & pushpins export using VB module + 8-11-2003 match journey route-points to pushpins, + integrate parts into single C/C++ exe (except istorage) + 9-11-2003 fixed invalid gpx. +10-11-2003 gpx import working for routes/tracks to s&t annotation lines. +13-11-2003 export as pcx5 for import into Garmin MapSource +20-11-2003 substantial cleanup + fixed 8byte alignment in properties.c + introduced 1byte alignment for journey analysis + understands most journey options +22-11-2003 explores UDM data +28-11-2003 imports pushpins + imports lines to v3 annotations (2002+) diff --git a/st2gpx/src/istorage license.txt b/st2gpx/src/istorage license.txt new file mode 100644 index 000000000..fde84dffe --- /dev/null +++ b/st2gpx/src/istorage license.txt @@ -0,0 +1,24 @@ +Copyright (c) 2001, Pabs (pabs3@zip.to) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/st2gpx/src/istorage-make license.txt b/st2gpx/src/istorage-make license.txt new file mode 100644 index 000000000..5ee1421bf --- /dev/null +++ b/st2gpx/src/istorage-make license.txt @@ -0,0 +1,24 @@ +Copyright (c) 2002, Pabs (pabs3@zip.to) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/st2gpx/src/journey.c b/st2gpx/src/journey.c new file mode 100644 index 000000000..e8fa65e52 --- /dev/null +++ b/st2gpx/src/journey.c @@ -0,0 +1,464 @@ +/* + journey.c + + Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format. + + Copyright (C) 2003 James Sherring, james_sherring@yahoo.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + + This app depends on istorage & istorage-make from Pabs (pabs3@zip.to) + and James Clark's Expat xml parser from http://www.libexpat.org/. + +*/ + +#include +#include +#include +#include +#include +#include + +#include "gpx.h" +#include "st2gpx.h" +#include "pushpins.h" +#include "ppinutil.h" + +#include "journey.h" + +float scaled2deg(int scaled_deg) +// there must be a simple single line calc +{ + double x=scaled_deg; + x = x*360/0x10000; + x = x/0x10000; + return (float)x; +} + +void jour_rtept_init(struct jour_rtept * nw) +{ +// struct jour_rtept_rec * nw=(struct jour_rtept_rec*)xmalloc(sizeof(struct jour_rtept_rec)); + nw->pthead_os=0; + nw->text1=NULL; + nw->ptmid_os=0; + nw->text2=NULL; + nw->pttail_os=0; + // pointer to pushpin owned by pushpinlist + nw->pushpin=NULL; + strcpy(nw->garmin_ident," "); +} + +void jour_rtept_delete(struct jour_rtept * jourpt) +{ + if (jourpt==NULL) + return; + xfree(jourpt->text1); + xfree(jourpt->text2); + // This is part of an array, so free the array + //xfree(jourpt); +} + +struct journey * journey_new() +{ + struct journey * nw = (struct journey*)xmalloc(sizeof(struct journey)); + nw->buf_len=0; + nw->buf=NULL; + + nw->rtept_list=NULL; + nw->jopts_os=0; + nw->jopts_eur8_os=0; + nw->jopts_usa8_os=0; + nw->jopts_usa10_os=0; + nw->avoid_os_list=NULL; + nw->trailer_os=0; + return nw; +} + +void journey_delete(struct journey * jour) +{ + int i; + if (jour==NULL) + return; + for(i=0; i< jour->count_rtepts; i++) + jour_rtept_delete(jour->rtept_list + i); + xfree(jour->rtept_list); + xfree(jour->avoid_os_list); + xfree(jour->buf); + xfree(jour); +} + + +struct journey * process_journey_stream (char* jour_in_file_name, + struct pushpin_safelist * ppplist) +{ + int j; + int readbyte; + int bytes2read=0; + + int max_read_more = 10000; + int readmore=0; + int status; + char readmorebuf[10000]; + + int UdId; +// double lat; +// double lon; +// double x; +// double y; +// double z; + + struct journey * jour = journey_new(); +// struct jour_rtept * thispt=NULL; + FILE* jour_in_file=NULL; + struct f_jour_pt_head * pt_head=NULL; + struct f_jour_opts_EUR_8* opts_eur8; + struct f_jour_opts_EUR_10* opts_eur10; + struct f_jour_opts_USA_8* opts_usa8; + struct f_jour_opts_USA_10* opts_usa10; + + printf("Processing Journey stream\n"); + + if ((jour_in_file = fopen(jour_in_file_name, "rb")) == NULL) + { + fprintf(stderr, "Quitting because I cannot open %s\n", jour_in_file_name); + exit(1); + } + + bytes2read=sizeof(struct f_jour_header); + jour->buf=(char*)xmalloc(jour->buf_len+bytes2read); + status = readbytes(jour_in_file, jour->buf, bytes2read); + jour->buf_len += bytes2read; + if (status!=bytes2read) + { + printf("Unexpected EOF in the Journey stream header\n"); + fclose(jour_in_file); + return jour; + } + jour->header_os = 0; + jour->count_rtepts = ((struct f_jour_header*)(jour->buf + jour->header_os))->cpoints; + + printf("got Journey file header with %d waypoints\n", jour->count_rtepts); + debug_pause(); + if (opts.explore_flag) + print_f_jour_header((struct f_jour_header*)(jour->buf + jour->header_os)); + + // an array of jour_rtept + jour->rtept_list = (struct jour_rtept *)xmalloc( + jour->count_rtepts*sizeof(struct jour_rtept)); + + for (j=0; j< jour->count_rtepts; j++) + { + jour_rtept_init(jour->rtept_list + j); + + // read pt header + bytes2read=sizeof(struct f_jour_pt_head); + jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read); + status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read); + if (status!=bytes2read) + { + printf("Unexpected EOF in the Journey stream, routepoint %d\n", j); + fclose(jour_in_file); + return jour; + } + jour->rtept_list[j].pthead_os=jour->buf_len; + jour->buf_len += bytes2read; + if (opts.explore_flag) + print_f_jour_pt_head((struct f_jour_pt_head*) + (jour->buf + jour->rtept_list[j].pthead_os)); + + // read pt text1 + bytes2read=((struct f_jour_pt_head*) + (jour->buf + jour->rtept_list[j].pthead_os))->cbtext1; + if (bytes2read) + { + jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read); + status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read); + if (status!=bytes2read) + { + printf("Unexpected EOF in the Journey stream, routepoint %d\n", j); + fclose(jour_in_file); + return jour; + } + jour->rtept_list[j].text1= (char*)malloc(bytes2read+1); + memcpy(jour->rtept_list[j].text1, jour->buf + jour->buf_len, bytes2read); + jour->rtept_list[j].text1[bytes2read]=0; + jour->buf_len += bytes2read; + + str2ascii(jour->rtept_list[j].text1); + } + if (opts.explore_flag) + printf("Got text1 %s\n", jour->rtept_list[j].text1); + + // read pt middle + bytes2read=sizeof(struct f_jour_pt_mid); + jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read); + status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read); + if (status!=bytes2read) + { + printf("Unexpected EOF in the Journey stream, routepoint %d\n", j); + fclose(jour_in_file); + return jour; + } + jour->rtept_list[j].ptmid_os=jour->buf_len; + jour->buf_len += bytes2read; + if (opts.explore_flag) + { + printf("dumping jour->rtept_list[%d].ptmid:\n", j); + printbuf(jour->buf + jour->rtept_list[j].ptmid_os, bytes2read); + } + + // read pt text2 + bytes2read=2*(((struct f_jour_pt_mid*)(jour->buf+jour->rtept_list[j].ptmid_os))->cbtext2); + if (bytes2read) + { + jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read); + status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read); + if (status!=bytes2read) + { + printf("Unexpected EOF in the Journey stream, routepoint %d\n", j); + fclose(jour_in_file); + return jour; + } + jour->rtept_list[j].text2= (char*)malloc(bytes2read+2); + memcpy(jour->rtept_list[j].text2, jour->buf + jour->buf_len, bytes2read); + jour->rtept_list[j].text2[bytes2read]=0; + jour->rtept_list[j].text2[bytes2read+1]=0; + jour->buf_len += bytes2read; + } + if (opts.explore_flag) + wprintf(L"Got text2 %s\n", jour->rtept_list[j].text2); + + // read pt tail + bytes2read=sizeof(struct f_jour_pt_tail); + jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read); + status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read); + if (status!=bytes2read) + { + printf("Unexpected EOF in the Journey stream, routepoint %d\n", j); + fclose(jour_in_file); + return jour; + } + jour->rtept_list[j].pttail_os=jour->buf_len; + jour->buf_len += bytes2read; + if (opts.explore_flag) + print_f_jour_pt_tail((struct f_jour_pt_tail*)(jour->buf +jour->rtept_list[j].pttail_os)); + + pt_head = (struct f_jour_pt_head*)(jour->buf+jour->rtept_list[j].pthead_os); +// UdId= ((struct f_jour_pt_head*)(jour->buf+jour->rtept_list[j].pthead_os))->UdId; + UdId = pt_head->UdId; + jour->rtept_list[j].pushpin = ppin_by_UdId(UdId, ppplist); + + if (jour->rtept_list[j].pushpin != NULL) + { + if (opts.verbose_flag > 5) + { + printf("Found matching pushpin:\n"); + printf("Pushpin name is: %s\n", jour->rtept_list[j].pushpin->UdName); + printf("Pushpin short note is: %s\n", jour->rtept_list[j].pushpin->NoteShort); + } +/* if (opts.verbose_flag > 4) + { + lat=jour->rtept_list[j].pushpin->lat; + lon=jour->rtept_list[j].pushpin->lon; + + printf("Matching pushpin Grid %#x=%d, Precision %#x=%d, MOBBId %#x=%d\n", + jour->rtept_list[j].pushpin->Grid, + jour->rtept_list[j].pushpin->Grid, + jour->rtept_list[j].pushpin->Precision, + jour->rtept_list[j].pushpin->Precision, + jour->rtept_list[j].pushpin->MOBBId, + jour->rtept_list[j].pushpin->MOBBId); + + printf("Matching pushpin Lat %f Lon %f\n", + jour->rtept_list[j].pushpin->lat, + jour->rtept_list[j].pushpin->lon); + + x = cos(lon*M_PI/180)*cos(lat*M_PI/180); + y = sin(lon*M_PI/180)*cos(lat*M_PI/180); + z = sin(lat*M_PI/180); + + printf("For matching pushpin X=%f Y=%f Z=%f\n", x,y,z); + } +*/ + } +/* else + { + printf("*** Warning *** Ignoring route point '%s' without matching pushpin\n", + jour->rtept_list[j].text1); + printf("(yes, I should do someting more clever than this).\n"); + if (UdId) + printf("There should have been a matching pushin because UdId=%d\n", UdId); + } +*/ + } + + // read jour generic opts + bytes2read=sizeof(struct f_jour_opts); + jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read); + status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read); + if (status!=bytes2read) + { + printf("Unexpected EOF in the Journey stream, options\n"); + fclose(jour_in_file); + return jour; + } + jour->jopts_os=jour->buf_len; + jour->buf_len += bytes2read; + if (opts.explore_flag) + print_f_jour_opts((struct f_jour_opts*)(jour->buf + jour->jopts_os)); + + // read file-version specific journey options + if( (opts.st_version_num==8) && (opts.isUSA==0)) + { + bytes2read=sizeof(struct f_jour_opts_EUR_8); + jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read); + status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read); + if (status!=bytes2read) + { + printf("Unexpected EOF in the Journey stream, options eur8\n"); + fclose(jour_in_file); + return jour; + } + jour->jopts_eur8_os=jour->buf_len; + jour->buf_len += bytes2read; + opts_eur8=(struct f_jour_opts_EUR_8*)(jour->buf + jour->jopts_eur8_os); + jour->count_avoid_regions = opts_eur8->count_avoid_regions; + if (opts.explore_flag) + print_f_jour_opts_EUR_8(opts_eur8); + } + else if( ( (opts.st_version_num==10) && (opts.isUSA==0) ) + || ( (opts.st_version_num==9) && (opts.isUSA==1) ) + || ( (opts.st_version_num==11) && (opts.isUSA==1) )) + { + bytes2read=sizeof(struct f_jour_opts_EUR_10); + jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read); + status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read); + if (status!=bytes2read) + { + printf("Unexpected EOF in the Journey stream, options eur10\n"); + fclose(jour_in_file); + return jour; + } + jour->jopts_eur10_os=jour->buf_len; + jour->buf_len += bytes2read; + opts_eur10=(struct f_jour_opts_EUR_10*)(jour->buf + jour->jopts_eur10_os); + jour->count_avoid_regions = opts_eur10->count_avoid_regions; + if (opts.explore_flag) + print_f_jour_opts_EUR_10(opts_eur10); + } + else if( (opts.st_version_num==8) && (opts.isUSA) ) + { + bytes2read=sizeof(struct f_jour_opts_USA_8); + jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read); + status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read); + if (status!=bytes2read) + { + printf("Unexpected EOF in the Journey stream, options usa8\n"); + fclose(jour_in_file); + return jour; + } + jour->jopts_usa8_os=jour->buf_len; + jour->buf_len += bytes2read; + opts_usa8=(struct f_jour_opts_USA_8*)(jour->buf + jour->jopts_usa8_os); + jour->count_avoid_regions = opts_usa8->count_avoid_regions; + if (opts.explore_flag) + print_f_jour_opts_USA_8(opts_usa8); + } + else if( (opts.st_version_num==10) && (opts.isUSA) ) + { + bytes2read=sizeof(struct f_jour_opts_USA_10); + jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read); + status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read); + if (status!=bytes2read) + { + printf("Unexpected EOF in the Journey stream, options usa10\n"); + fclose(jour_in_file); + return jour; + } + jour->jopts_usa10_os=jour->buf_len; + jour->buf_len += bytes2read; + opts_usa10=(struct f_jour_opts_USA_10*)(jour->buf + jour->jopts_usa10_os); + jour->count_avoid_regions = opts_usa10->count_avoid_regions; + if (opts.explore_flag) + print_f_jour_opts_USA_10(opts_usa10); + } + else + printf("I dont yet understand the structure of the Journey options for this file version.\n"); + + if (jour->count_avoid_regions >0) + { + printf("Reading %d avoid regions", jour->count_avoid_regions); + + // an array of pointers to f_jour_avoid + jour->avoid_os_list=(int*)xmalloc((jour->count_avoid_regions)*sizeof(int)); + + for (j=0; j< jour->count_avoid_regions; j++) + { + // read avoid record + bytes2read=sizeof(struct f_jour_avoid); + jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read); + status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read); + if (status!=bytes2read) + { + printf("Unexpected EOF in the Journey stream, avoid record %d\n", j); + fclose(jour_in_file); + return jour; + } + jour->avoid_os_list[j]= jour->buf_len; + jour->buf_len += bytes2read; + if (opts.explore_flag) + print_f_jour_avoid((struct f_jour_avoid*)(jour->buf + jour->avoid_os_list[j])); + } + } + + // read journey tail + bytes2read=sizeof(struct f_jour_trailer); + jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read); + status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read); + if (status!=bytes2read) + { + printf("Unexpected EOF in the Journey stream, trailer\n"); + fclose(jour_in_file); + return jour; + } + jour->trailer_os=jour->buf_len; + jour->buf_len += bytes2read; + if (opts.explore_flag) + print_f_jour_trailer((struct f_jour_trailer*)(jour->buf + jour->trailer_os)); + + readmore=0; + if ((readbyte = getc(jour_in_file))!=EOF) + { + fprintf (stderr, "Did not finish reading journey file at EOF\n"); + + do { + readmorebuf[readmore]=(char)readbyte; + readmore++; + if (readmore>max_read_more) + break; + } while ((readbyte = getc(jour_in_file))!=EOF); + + printf("read a further %d bytes past expected eof\n", readmore); + printbuf(readmorebuf, readmore); + } + + fclose(jour_in_file); + + printf("Finished processing Journey stream.\n"); + fflush(stdout); + + return jour; +} diff --git a/st2gpx/src/journey.h b/st2gpx/src/journey.h new file mode 100644 index 000000000..074038429 --- /dev/null +++ b/st2gpx/src/journey.h @@ -0,0 +1,382 @@ +/* + journey.h + + Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format. + + Copyright (C) 2003 James Sherring, james_sherring@yahoo.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + + This app depends on istorage & istorage-make from Pabs (pabs3@zip.to) + and James Clark's Expat xml parser from http://www.libexpat.org/. + +*/ +#ifdef __cplusplus +extern "C" { +#endif + +#define JOUR_FILE_HEAD_LEN 32 +#define JOUR_FILE_TAIL_LEN_EUR_V8 430 +#define JOUR_FILE_TAIL_LEN_USA_V8 426 +#define JOUR_FILE_TAIL_LEN_USA_V10 396 + +// + text1 +2*text2 +#define JOUR_WPTREC_LEN 121 + +#define JOUR_FILE_OS_NUMREC 16 + +#define JOURWPT_REC_HEAD_LEN 41 + +#define JOURWPT_RECOS_WPTNUM 0 +#define JOURWPT_RECOS_STR1LEN 40 +#define JOURWPT_RECOS_STR1 41 +// + val(JOURWPT_RECOS_STR1LEN) +#define JOURWPT_RECOS_STR2LEN 44 +#define JOURWPT_RECOS_STR2 45 + +// Still to test in Journey: +// * points located by address Vs by mouse Vs by pushpin +// * avoid areas +// * drag route +typedef struct f_jour_header +{ + int iunkn0; + int iunkn1; + int iunkn2; + int iunkn3; + unsigned int cpoints; + int iunkn4; + int iunkn5; + int iunkn6; +} tag_f_jour_header; + +typedef struct f_jour_pt_head +{ + // DB prim key for pushpin + // 0 if no pushpin + int UdId; + int stop_dur_secs; + int iunkn0; + int sched_arrive_flag; + // This may have more meaning, + // it changes with small changes in route. + // Perhaps just small changes in route time? + int sched_depart_flag; + int arrive_time_secs; + int depart_time_secs; + int iunkn1; + // The coords for the actual journey point, not neccessarily on a road. + //ie =lat/360*2^32 + int scaled_lon; + int scaled_lat; + unsigned char cbtext1; +} tag_f_jour_pt_head; + +// then jour_pt_head.cbtext1 bytes of text + +typedef struct f_jour_pt_mid +{ + // this just seems to be a const FF FE FF + char mid_tag[3]; + unsigned char cbtext2; +} tag_f_jour_pt_mid; + +// then 2*jour_pt_mid.cbtext2 bytes of wide text + +typedef struct f_jour_pt_tail +{ + // 0=fastest + // 1=shortest + // 2=prefered + // (from previous jour_pt) + int route_rd_pref; // =0 + // these seem const + int iunkn0; // = 1 + int iunkn1; // = 4 + int iunkn2; // =0 + int iunkn3; // =1 + int road_id; + double dist_along_rd_frac; + // The coords for the arrival point on the road + //ie =lat/360*2^32 + int rd_arrive_sc_lat; + int rd_arrive_sc_lon; + // The coords for the departure point on the road + int rd_depart_sc_lat; + int rd_depart_sc_lon; + int iunkn8; // 4 + int iunkn9; // 1 + int iunkn10; // 1 + int iunkn11; // 6 + int iunkn12; // 1 + int iunkn13; // 1 + // ? size ? + int iunkn14; // 30 +} tag_f_jour_pt_tail; + +typedef struct f_jour_opts +{ + // @00 + short int siunkn0; + float funkn0; + double toll_rd_pref; + double motorway_pref; // ok + // @16 + double major_rd_pref; + double minor_rd_pref; + // @26 + double ferry_pref; + int iunkn0; + // @32 + int iunkn1; + int iunkn2; + double fuel_price; // ok + // @42 + // 3 = per US Gallon + int iunkn3; + int fuel_price_unit; + int iunkn4; + double tank_capacity; // ok + // @56 + // 2 = liters + int tank_capacity_units; + double tank_start_level; // ok + // @62 + double tank_warn_level; // ok + int iunkn5; + double fuel_use_city; // ok + // @76 + // 3 = liters/100k + int fuel_use_city_unit; + int iunkn6; + double fuel_use_mway; //ok + // @86 + // 3 = liters/100k + int fuel_use_mway_unit; + int iunkn7; + double mway_speed; //ok + // @96 + int mway_speed_unit; + int iunkn9; + double lim_acc_speed; //ok + // @a6 + int lim_acc_speed_unit; + int iunkn11; + double maj_rd_speed; //ok + // @b6 + int maj_rd_speed_unit; + int iunkn13; + double min_rd_speed; //ok + // @c6 + int min_rd_speed_unit; + int iunkn15; + double street_speed; //ok + // @d6 + int street_speed_unit; + int iunkn17; + int iunkn18; + float funkn1; + // @e6 + int iunkn19; + int iunkn20; + int iunkn21; + float funkn2; + // @f6 + int iunkn22; + int iunkn23; + int iunkn24; + float funkn3; + // @106 + int iunkn25; + int iunkn26; + int iunkn27; + float funkn4; + // @116 + int iunkn28; + int iunkn29; + int iunkn30; + float funkn5; + // @126 + int iunkn31; + int iunkn32; + int iunkn33; + int start_drv_hr; //ok + // @136 + int start_drv_min; //ok + int iunkn34; + int end_drv_hr; //ok + int end_drv_min; //ok + // @146 + int fuel_warn_flag; + int iunkn35; + int fuel_fixed_rate_flag; + int iunkn36; + // @156 + int fuel_cost_dist; + int route_flex_secs; //ok + int iunkn37; + int rest_flag; + // @166 + int rest_dur_secs; + int rest_interval_secs; +} tag_jour_opts; + +typedef struct f_jour_opts_EUR_8 +{ + int iunkn38; + int iunkn39; + // @176 + int iunkn40; + int iunkn41; + int iunkn42; + short int siunkn1; + // @184 + int route_show_tm; + int route_show_dist; + int route_show_inst; + // @190 + int route_show_for; + int route_show_to; + int route_show_font_size; + int iunkn43; + // @1a0 + // not in usa version8 + int iunkn44; + unsigned short int count_avoid_regions; +} tag_f_jour_opts_EUR_8; + +// Also works for USA9 and USA11 +typedef struct f_jour_opts_EUR_10 +{ + int iunkn38; + int iunkn39; + // @176 + int iunkn40; + int iunkn41; + int iunkn42; + + unsigned short int count_avoid_regions; +} tag_f_jour_opts_EUR_10; + +typedef struct f_jour_opts_USA_8 +{ + int iunkn38; + int iunkn39; + // @176 + int iunkn40; + int iunkn41; + int iunkn42; + short int siunkn1; + // @184 + int iunkn43; + int iunkn44; + int iunkn45; + // @190 + int iunkn46; + int iunkn47; + int iunkn48; + int iunkn49; + // @1a0 + unsigned short int count_avoid_regions; +} tag_f_jour_opts_USA_8; + +typedef struct f_jour_opts_USA_10 +{ + int iunkn38; + int iunkn39; + // @176 + int iunkn40; + int iunkn41; + int iunkn42; + short int siunkn1; + // @184 + int iunkn43; + int iunkn44; + unsigned short int count_avoid_regions; +} tag_f_jour_opts_USA_10; + + +typedef struct f_jour_avoid +{ + float x; + float y; + float z; + int iunkn0; + int iunkn1; + int iunkn2; + int iunkn3; + int iunkn4; + int iunkn5; + // avoid num? annot? + int annot_num; +} tag_f_jour_avoid; + + +typedef struct f_jour_trailer +{ + int iunkn0; // =0x65 + int iunkn1; +} f_tag_jour_trailer; + +typedef struct jour_rtept +{ + int pthead_os; + // mem owned by this struct, as buf does not have terminating null + char* text1; + int ptmid_os; + // mem owned by this struct, as buf does not have terminating null + char* text2; + int pttail_os; + // pointer to pushpin owned by pushpinlist + struct pushpin* pushpin; + char garmin_ident[7]; +} tag_jour_trept; + +struct jour_rtept_rec * jour_rtept_rec_new(); +void jour_rtept_rec_delete(struct jour_rtept_rec * jourpt_rec); + +typedef struct journey +{ + int buf_len; + char* buf; + // We need to use nasty unsigned shorts if we compare to ->header->cpoints + int count_rtepts; + // a convenience for looking in multiple version opts + int count_avoid_regions; + int header_os; + // an array of jour_rtept + struct jour_rtept * rtept_list; + int jopts_os; + int jopts_eur8_os; + int jopts_eur10_os; + int jopts_usa8_os; + int jopts_usa10_os; + // an array of ofsets to f_jour_avoid + int * avoid_os_list; + int trailer_os; +} tag_journey; + +float scaled2deg(int scaled_deg); + +struct journey * journey_new(); +void journey_delete(struct journey * jour); + +struct journey * process_journey_stream (char* jour_in_file_name, struct pushpin_safelist * ppplist); + + +#ifdef __cplusplus +} +#endif diff --git a/st2gpx/src/msado15.tlh b/st2gpx/src/msado15.tlh new file mode 100644 index 000000000..b49246411 --- /dev/null +++ b/st2gpx/src/msado15.tlh @@ -0,0 +1,2997 @@ +// Created by Microsoft (R) C/C++ Compiler Version 12.00.8168.0 (1f62c7b3). +// +// msado15.tlh +// +// C++ source equivalent of Win32 type library msado15.dll +// compiler-generated file created 11/21/03 at 18:38:05 - DO NOT EDIT! + +#pragma once +#pragma pack(push, 8) + +#include + +namespace ADODB { + +// +// Forward references and typedefs +// + +typedef enum SearchDirectionEnum SearchDirection; +struct __declspec(uuid("00000512-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ _Collection; +struct __declspec(uuid("00000513-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ _DynaCollection; +struct __declspec(uuid("00000534-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ _ADO; +struct __declspec(uuid("00000504-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ Properties; +struct __declspec(uuid("00000503-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ Property; +struct __declspec(uuid("00000500-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ Error; +struct __declspec(uuid("00000501-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ Errors; +struct __declspec(uuid("00000508-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ Command15; +struct __declspec(uuid("00000550-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ _Connection; +struct __declspec(uuid("00000515-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ Connection15; +struct __declspec(uuid("00000556-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ _Recordset; +struct __declspec(uuid("00000555-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ Recordset21; +struct __declspec(uuid("0000054f-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ Recordset20; +struct __declspec(uuid("0000050e-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ Recordset15; +struct __declspec(uuid("00000564-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ Fields; +struct __declspec(uuid("0000054d-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ Fields20; +struct __declspec(uuid("00000506-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ Fields15; +struct __declspec(uuid("00000569-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ Field; +struct __declspec(uuid("0000054c-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ Field20; +struct __declspec(uuid("0000050c-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ _Parameter; +struct __declspec(uuid("0000050d-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ Parameters; +struct __declspec(uuid("0000054e-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ _Command; +struct __declspec(uuid("00000402-0000-0010-8000-00aa006d2ea4")) +/* interface */ ConnectionEventsVt; +struct __declspec(uuid("00000403-0000-0010-8000-00aa006d2ea4")) +/* interface */ RecordsetEventsVt; +struct __declspec(uuid("00000400-0000-0010-8000-00aa006d2ea4")) +/* dispinterface */ ConnectionEvents; +struct __declspec(uuid("00000266-0000-0010-8000-00aa006d2ea4")) +/* dispinterface */ RecordsetEvents; +struct __declspec(uuid("00000516-0000-0010-8000-00aa006d2ea4")) +/* interface */ ADOConnectionConstruction15; +struct __declspec(uuid("00000551-0000-0010-8000-00aa006d2ea4")) +/* interface */ ADOConnectionConstruction; +struct /* coclass */ Connection; +struct __declspec(uuid("00000562-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ _Record; +struct /* coclass */ Record; +struct __declspec(uuid("00000563-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ IRecFields; +struct __declspec(uuid("00000565-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ _Stream; +struct /* coclass */ Stream; +struct __declspec(uuid("00000567-0000-0010-8000-00aa006d2ea4")) +/* interface */ ADORecordConstruction; +struct __declspec(uuid("00000568-0000-0010-8000-00aa006d2ea4")) +/* interface */ ADOStreamConstruction; +struct __declspec(uuid("00000517-0000-0010-8000-00aa006d2ea4")) +/* interface */ ADOCommandConstruction; +struct /* coclass */ Command; +struct /* coclass */ Recordset; +struct __declspec(uuid("00000283-0000-0010-8000-00aa006d2ea4")) +/* interface */ ADORecordsetConstruction; +struct __declspec(uuid("00000505-0000-0010-8000-00aa006d2ea4")) +/* dual interface */ Field15; +struct /* coclass */ Parameter; + +// +// Smart pointer typedef declarations +// + +_COM_SMARTPTR_TYPEDEF(_Collection, __uuidof(_Collection)); +_COM_SMARTPTR_TYPEDEF(_DynaCollection, __uuidof(_DynaCollection)); +_COM_SMARTPTR_TYPEDEF(_ADO, __uuidof(_ADO)); +_COM_SMARTPTR_TYPEDEF(Properties, __uuidof(Properties)); +_COM_SMARTPTR_TYPEDEF(Property, __uuidof(Property)); +_COM_SMARTPTR_TYPEDEF(Error, __uuidof(Error)); +_COM_SMARTPTR_TYPEDEF(Errors, __uuidof(Errors)); +_COM_SMARTPTR_TYPEDEF(Command15, __uuidof(Command15)); +_COM_SMARTPTR_TYPEDEF(Connection15, __uuidof(Connection15)); +_COM_SMARTPTR_TYPEDEF(_Connection, __uuidof(_Connection)); +_COM_SMARTPTR_TYPEDEF(Recordset15, __uuidof(Recordset15)); +_COM_SMARTPTR_TYPEDEF(Recordset20, __uuidof(Recordset20)); +_COM_SMARTPTR_TYPEDEF(Recordset21, __uuidof(Recordset21)); +_COM_SMARTPTR_TYPEDEF(_Recordset, __uuidof(_Recordset)); +_COM_SMARTPTR_TYPEDEF(Fields15, __uuidof(Fields15)); +_COM_SMARTPTR_TYPEDEF(Fields20, __uuidof(Fields20)); +_COM_SMARTPTR_TYPEDEF(Fields, __uuidof(Fields)); +_COM_SMARTPTR_TYPEDEF(Field20, __uuidof(Field20)); +_COM_SMARTPTR_TYPEDEF(Field, __uuidof(Field)); +_COM_SMARTPTR_TYPEDEF(_Parameter, __uuidof(_Parameter)); +_COM_SMARTPTR_TYPEDEF(Parameters, __uuidof(Parameters)); +_COM_SMARTPTR_TYPEDEF(_Command, __uuidof(_Command)); +_COM_SMARTPTR_TYPEDEF(ConnectionEventsVt, __uuidof(ConnectionEventsVt)); +_COM_SMARTPTR_TYPEDEF(RecordsetEventsVt, __uuidof(RecordsetEventsVt)); +_COM_SMARTPTR_TYPEDEF(ConnectionEvents, __uuidof(IDispatch)); +_COM_SMARTPTR_TYPEDEF(RecordsetEvents, __uuidof(IDispatch)); +_COM_SMARTPTR_TYPEDEF(ADOConnectionConstruction15, __uuidof(ADOConnectionConstruction15)); +_COM_SMARTPTR_TYPEDEF(ADOConnectionConstruction, __uuidof(ADOConnectionConstruction)); +_COM_SMARTPTR_TYPEDEF(_Record, __uuidof(_Record)); +_COM_SMARTPTR_TYPEDEF(IRecFields, __uuidof(IRecFields)); +_COM_SMARTPTR_TYPEDEF(_Stream, __uuidof(_Stream)); +_COM_SMARTPTR_TYPEDEF(ADORecordConstruction, __uuidof(ADORecordConstruction)); +_COM_SMARTPTR_TYPEDEF(ADOStreamConstruction, __uuidof(ADOStreamConstruction)); +_COM_SMARTPTR_TYPEDEF(ADOCommandConstruction, __uuidof(ADOCommandConstruction)); +_COM_SMARTPTR_TYPEDEF(ADORecordsetConstruction, __uuidof(ADORecordsetConstruction)); +_COM_SMARTPTR_TYPEDEF(Field15, __uuidof(Field15)); + +// +// Type library items +// + +enum CursorTypeEnum +{ + adOpenUnspecified = -1, + adOpenForwardOnly = 0, + adOpenKeyset = 1, + adOpenDynamic = 2, + adOpenStatic = 3 +}; + +enum CursorOptionEnum +{ + adHoldRecords = 256, + adMovePrevious = 512, + adAddNew = 16778240, + adDelete = 16779264, + adUpdate = 16809984, + adBookmark = 8192, + adApproxPosition = 16384, + adUpdateBatch = 65536, + adResync = 131072, + adNotify = 262144, + adFind = 524288, + adSeek = 4194304, + adIndex = 8388608 +}; + +enum LockTypeEnum +{ + adLockUnspecified = -1, + adLockReadOnly = 1, + adLockPessimistic = 2, + adLockOptimistic = 3, + adLockBatchOptimistic = 4 +}; + +enum ExecuteOptionEnum +{ + adOptionUnspecified = -1, + adAsyncExecute = 16, + adAsyncFetch = 32, + adAsyncFetchNonBlocking = 64, + adExecuteNoRecords = 128 +}; + +enum ConnectOptionEnum +{ + adConnectUnspecified = -1, + adAsyncConnect = 16 +}; + +enum ObjectStateEnum +{ + adStateClosed = 0, + adStateOpen = 1, + adStateConnecting = 2, + adStateExecuting = 4, + adStateFetching = 8 +}; + +enum CursorLocationEnum +{ + adUseNone = 1, + adUseServer = 2, + adUseClient = 3, + adUseClientBatch = 3 +}; + +enum DataTypeEnum +{ + adEmpty = 0, + adTinyInt = 16, + adSmallInt = 2, + adInteger = 3, + adBigInt = 20, + adUnsignedTinyInt = 17, + adUnsignedSmallInt = 18, + adUnsignedInt = 19, + adUnsignedBigInt = 21, + adSingle = 4, + adDouble = 5, + adCurrency = 6, + adDecimal = 14, + adNumeric = 131, + adBoolean = 11, + adError = 10, + adUserDefined = 132, + adVariant = 12, + adIDispatch = 9, + adIUnknown = 13, + adGUID = 72, + adDate = 7, + adDBDate = 133, + adDBTime = 134, + adDBTimeStamp = 135, + adBSTR = 8, + adChar = 129, + adVarChar = 200, + adLongVarChar = 201, + adWChar = 130, + adVarWChar = 202, + adLongVarWChar = 203, + adBinary = 128, + adVarBinary = 204, + adLongVarBinary = 205, + adChapter = 136, + adFileTime = 64, + adPropVariant = 138, + adVarNumeric = 139, + adArray = 8192 +}; + +enum FieldAttributeEnum +{ + adFldUnspecified = -1, + adFldMayDefer = 2, + adFldUpdatable = 4, + adFldUnknownUpdatable = 8, + adFldFixed = 16, + adFldIsNullable = 32, + adFldMayBeNull = 64, + adFldLong = 128, + adFldRowID = 256, + adFldRowVersion = 512, + adFldCacheDeferred = 4096, + adFldIsChapter = 8192, + adFldNegativeScale = 16384, + adFldKeyColumn = 32768, + adFldIsRowURL = 65536, + adFldIsDefaultStream = 131072, + adFldIsCollection = 262144 +}; + +enum EditModeEnum +{ + adEditNone = 0, + adEditInProgress = 1, + adEditAdd = 2, + adEditDelete = 4 +}; + +enum RecordStatusEnum +{ + adRecOK = 0, + adRecNew = 1, + adRecModified = 2, + adRecDeleted = 4, + adRecUnmodified = 8, + adRecInvalid = 16, + adRecMultipleChanges = 64, + adRecPendingChanges = 128, + adRecCanceled = 256, + adRecCantRelease = 1024, + adRecConcurrencyViolation = 2048, + adRecIntegrityViolation = 4096, + adRecMaxChangesExceeded = 8192, + adRecObjectOpen = 16384, + adRecOutOfMemory = 32768, + adRecPermissionDenied = 65536, + adRecSchemaViolation = 131072, + adRecDBDeleted = 262144 +}; + +enum GetRowsOptionEnum +{ + adGetRowsRest = -1 +}; + +enum PositionEnum +{ + adPosUnknown = -1, + adPosBOF = -2, + adPosEOF = -3 +}; + +enum BookmarkEnum +{ + adBookmarkCurrent = 0, + adBookmarkFirst = 1, + adBookmarkLast = 2 +}; + +enum MarshalOptionsEnum +{ + adMarshalAll = 0, + adMarshalModifiedOnly = 1 +}; + +enum AffectEnum +{ + adAffectCurrent = 1, + adAffectGroup = 2, + adAffectAll = 3, + adAffectAllChapters = 4 +}; + +enum ResyncEnum +{ + adResyncUnderlyingValues = 1, + adResyncAllValues = 2 +}; + +enum CompareEnum +{ + adCompareLessThan = 0, + adCompareEqual = 1, + adCompareGreaterThan = 2, + adCompareNotEqual = 3, + adCompareNotComparable = 4 +}; + +enum FilterGroupEnum +{ + adFilterNone = 0, + adFilterPendingRecords = 1, + adFilterAffectedRecords = 2, + adFilterFetchedRecords = 3, + adFilterPredicate = 4, + adFilterConflictingRecords = 5 +}; + +enum SearchDirectionEnum +{ + adSearchForward = 1, + adSearchBackward = -1 +}; + +enum PersistFormatEnum +{ + adPersistADTG = 0, + adPersistXML = 1 +}; + +enum StringFormatEnum +{ + adClipString = 2 +}; + +enum ConnectPromptEnum +{ + adPromptAlways = 1, + adPromptComplete = 2, + adPromptCompleteRequired = 3, + adPromptNever = 4 +}; + +enum ConnectModeEnum +{ + adModeUnknown = 0, + adModeRead = 1, + adModeWrite = 2, + adModeReadWrite = 3, + adModeShareDenyRead = 4, + adModeShareDenyWrite = 8, + adModeShareExclusive = 12, + adModeShareDenyNone = 16, + adModeRecursive = 4194304 +}; + +enum RecordCreateOptionsEnum +{ + adCreateCollection = 8192, + adCreateStructDoc = -2147483648, + adCreateNonCollection = 0, + adOpenIfExists = 33554432, + adCreateOverwrite = 67108864, + adFailIfNotExists = -1 +}; + +enum RecordOpenOptionsEnum +{ + adOpenRecordUnspecified = -1, + adOpenSource = 8388608, + adOpenAsync = 4096, + adDelayFetchStream = 16384, + adDelayFetchFields = 32768 +}; + +enum IsolationLevelEnum +{ + adXactUnspecified = -1, + adXactChaos = 16, + adXactReadUncommitted = 256, + adXactBrowse = 256, + adXactCursorStability = 4096, + adXactReadCommitted = 4096, + adXactRepeatableRead = 65536, + adXactSerializable = 1048576, + adXactIsolated = 1048576 +}; + +enum XactAttributeEnum +{ + adXactCommitRetaining = 131072, + adXactAbortRetaining = 262144, + adXactAsyncPhaseOne = 524288, + adXactSyncPhaseOne = 1048576 +}; + +enum PropertyAttributesEnum +{ + adPropNotSupported = 0, + adPropRequired = 1, + adPropOptional = 2, + adPropRead = 512, + adPropWrite = 1024 +}; + +enum ErrorValueEnum +{ + adErrProviderFailed = 3000, + adErrInvalidArgument = 3001, + adErrOpeningFile = 3002, + adErrReadFile = 3003, + adErrWriteFile = 3004, + adErrNoCurrentRecord = 3021, + adErrIllegalOperation = 3219, + adErrCantChangeProvider = 3220, + adErrInTransaction = 3246, + adErrFeatureNotAvailable = 3251, + adErrItemNotFound = 3265, + adErrObjectInCollection = 3367, + adErrObjectNotSet = 3420, + adErrDataConversion = 3421, + adErrObjectClosed = 3704, + adErrObjectOpen = 3705, + adErrProviderNotFound = 3706, + adErrBoundToCommand = 3707, + adErrInvalidParamInfo = 3708, + adErrInvalidConnection = 3709, + adErrNotReentrant = 3710, + adErrStillExecuting = 3711, + adErrOperationCancelled = 3712, + adErrStillConnecting = 3713, + adErrInvalidTransaction = 3714, + adErrNotExecuting = 3715, + adErrUnsafeOperation = 3716, + adwrnSecurityDialog = 3717, + adwrnSecurityDialogHeader = 3718, + adErrIntegrityViolation = 3719, + adErrPermissionDenied = 3720, + adErrDataOverflow = 3721, + adErrSchemaViolation = 3722, + adErrSignMismatch = 3723, + adErrCantConvertvalue = 3724, + adErrCantCreate = 3725, + adErrColumnNotOnThisRow = 3726, + adErrURLDoesNotExist = 3727, + adErrTreePermissionDenied = 3728, + adErrInvalidURL = 3729, + adErrResourceLocked = 3730, + adErrResourceExists = 3731, + adErrCannotComplete = 3732, + adErrVolumeNotFound = 3733, + adErrOutOfSpace = 3734, + adErrResourceOutOfScope = 3735, + adErrUnavailable = 3736, + adErrURLNamedRowDoesNotExist = 3737, + adErrDelResOutOfScope = 3738, + adErrPropInvalidColumn = 3739, + adErrPropInvalidOption = 3740, + adErrPropInvalidValue = 3741, + adErrPropConflicting = 3742, + adErrPropNotAllSettable = 3743, + adErrPropNotSet = 3744, + adErrPropNotSettable = 3745, + adErrPropNotSupported = 3746, + adErrCatalogNotSet = 3747, + adErrCantChangeConnection = 3748, + adErrFieldsUpdateFailed = 3749, + adErrDenyNotSupported = 3750, + adErrDenyTypeNotSupported = 3751 +}; + +enum ParameterAttributesEnum +{ + adParamSigned = 16, + adParamNullable = 64, + adParamLong = 128 +}; + +enum ParameterDirectionEnum +{ + adParamUnknown = 0, + adParamInput = 1, + adParamOutput = 2, + adParamInputOutput = 3, + adParamReturnValue = 4 +}; + +enum CommandTypeEnum +{ + adCmdUnspecified = -1, + adCmdUnknown = 8, + adCmdText = 1, + adCmdTable = 2, + adCmdStoredProc = 4, + adCmdFile = 256, + adCmdTableDirect = 512 +}; + +enum EventStatusEnum +{ + adStatusOK = 1, + adStatusErrorsOccurred = 2, + adStatusCantDeny = 3, + adStatusCancel = 4, + adStatusUnwantedEvent = 5 +}; + +enum EventReasonEnum +{ + adRsnAddNew = 1, + adRsnDelete = 2, + adRsnUpdate = 3, + adRsnUndoUpdate = 4, + adRsnUndoAddNew = 5, + adRsnUndoDelete = 6, + adRsnRequery = 7, + adRsnResynch = 8, + adRsnClose = 9, + adRsnMove = 10, + adRsnFirstChange = 11, + adRsnMoveFirst = 12, + adRsnMoveNext = 13, + adRsnMovePrevious = 14, + adRsnMoveLast = 15 +}; + +enum SchemaEnum +{ + adSchemaProviderSpecific = -1, + adSchemaAsserts = 0, + adSchemaCatalogs = 1, + adSchemaCharacterSets = 2, + adSchemaCollations = 3, + adSchemaColumns = 4, + adSchemaCheckConstraints = 5, + adSchemaConstraintColumnUsage = 6, + adSchemaConstraintTableUsage = 7, + adSchemaKeyColumnUsage = 8, + adSchemaReferentialContraints = 9, + adSchemaReferentialConstraints = 9, + adSchemaTableConstraints = 10, + adSchemaColumnsDomainUsage = 11, + adSchemaIndexes = 12, + adSchemaColumnPrivileges = 13, + adSchemaTablePrivileges = 14, + adSchemaUsagePrivileges = 15, + adSchemaProcedures = 16, + adSchemaSchemata = 17, + adSchemaSQLLanguages = 18, + adSchemaStatistics = 19, + adSchemaTables = 20, + adSchemaTranslations = 21, + adSchemaProviderTypes = 22, + adSchemaViews = 23, + adSchemaViewColumnUsage = 24, + adSchemaViewTableUsage = 25, + adSchemaProcedureParameters = 26, + adSchemaForeignKeys = 27, + adSchemaPrimaryKeys = 28, + adSchemaProcedureColumns = 29, + adSchemaDBInfoKeywords = 30, + adSchemaDBInfoLiterals = 31, + adSchemaCubes = 32, + adSchemaDimensions = 33, + adSchemaHierarchies = 34, + adSchemaLevels = 35, + adSchemaMeasures = 36, + adSchemaProperties = 37, + adSchemaMembers = 38, + adSchemaTrustees = 39 +}; + +enum FieldStatusEnum +{ + adFieldOK = 0, + adFieldCantConvertValue = 2, + adFieldIsNull = 3, + adFieldTruncated = 4, + adFieldSignMismatch = 5, + adFieldDataOverflow = 6, + adFieldCantCreate = 7, + adFieldUnavailable = 8, + adFieldPermissionDenied = 9, + adFieldIntegrityViolation = 10, + adFieldSchemaViolation = 11, + adFieldBadStatus = 12, + adFieldDefault = 13, + adFieldIgnore = 15, + adFieldDoesNotExist = 16, + adFieldInvalidURL = 17, + adFieldResourceLocked = 18, + adFieldResourceExists = 19, + adFieldCannotComplete = 20, + adFieldVolumeNotFound = 21, + adFieldOutOfSpace = 22, + adFieldCannotDeleteSource = 23, + adFieldReadOnly = 24, + adFieldResourceOutOfScope = 25, + adFieldAlreadyExists = 26, + adFieldPendingInsert = 65536, + adFieldPendingDelete = 131072, + adFieldPendingChange = 262144, + adFieldPendingUnknown = 524288, + adFieldPendingUnknownDelete = 1048576 +}; + +enum SeekEnum +{ + adSeekFirstEQ = 1, + adSeekLastEQ = 2, + adSeekAfterEQ = 4, + adSeekAfter = 8, + adSeekBeforeEQ = 16, + adSeekBefore = 32 +}; + +enum ADCPROP_UPDATECRITERIA_ENUM +{ + adCriteriaKey = 0, + adCriteriaAllCols = 1, + adCriteriaUpdCols = 2, + adCriteriaTimeStamp = 3 +}; + +enum ADCPROP_ASYNCTHREADPRIORITY_ENUM +{ + adPriorityLowest = 1, + adPriorityBelowNormal = 2, + adPriorityNormal = 3, + adPriorityAboveNormal = 4, + adPriorityHighest = 5 +}; + +enum ADCPROP_AUTORECALC_ENUM +{ + adRecalcUpFront = 0, + adRecalcAlways = 1 +}; + +enum ADCPROP_UPDATERESYNC_ENUM +{ + adResyncNone = 0, + adResyncAutoIncrement = 1, + adResyncConflicts = 2, + adResyncUpdates = 4, + adResyncInserts = 8, + adResyncAll = 15 +}; + +enum MoveRecordOptionsEnum +{ + adMoveUnspecified = -1, + adMoveOverWrite = 1, + adMoveDontUpdateLinks = 2, + adMoveAllowEmulation = 4 +}; + +enum CopyRecordOptionsEnum +{ + adCopyUnspecified = -1, + adCopyOverWrite = 1, + adCopyAllowEmulation = 4, + adCopyNonRecursive = 2 +}; + +enum StreamTypeEnum +{ + adTypeBinary = 1, + adTypeText = 2 +}; + +enum LineSeparatorEnum +{ + adLF = 10, + adCR = 13, + adCRLF = -1 +}; + +enum StreamOpenOptionsEnum +{ + adOpenStreamUnspecified = -1, + adOpenStreamAsync = 1, + adOpenStreamFromRecord = 4 +}; + +enum StreamWriteEnum +{ + adWriteChar = 0, + adWriteLine = 1, + stWriteChar = 0, + stWriteLine = 1 +}; + +enum SaveOptionsEnum +{ + adSaveCreateNotExist = 1, + adSaveCreateOverWrite = 2 +}; + +enum FieldEnum +{ + adDefaultStream = -1, + adRecordURL = -2 +}; + +enum StreamReadEnum +{ + adReadAll = -1, + adReadLine = -2 +}; + +enum RecordTypeEnum +{ + adSimpleRecord = 0, + adCollectionRecord = 1, + adStructDoc = 2 +}; + +struct __declspec(uuid("00000512-0000-0010-8000-00aa006d2ea4")) +_Collection : IDispatch +{ + // + // Property data + // + + __declspec(property(get=GetCount)) + long Count; + + // + // Wrapper methods for error-handling + // + + long GetCount ( ); + IUnknownPtr _NewEnum ( ); + HRESULT Refresh ( ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_Count ( + long * c ) = 0; + virtual HRESULT __stdcall raw__NewEnum ( + IUnknown * * ppvObject ) = 0; + virtual HRESULT __stdcall raw_Refresh ( ) = 0; +}; + +struct __declspec(uuid("00000513-0000-0010-8000-00aa006d2ea4")) +_DynaCollection : _Collection +{ + // + // Wrapper methods for error-handling + // + + HRESULT Append ( + IDispatch * Object ); + HRESULT Delete ( + const _variant_t & Index ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall raw_Append ( + IDispatch * Object ) = 0; + virtual HRESULT __stdcall raw_Delete ( + VARIANT Index ) = 0; +}; + +struct __declspec(uuid("00000534-0000-0010-8000-00aa006d2ea4")) +_ADO : IDispatch +{ + // + // Property data + // + + __declspec(property(get=GetProperties)) + PropertiesPtr Properties; + + // + // Wrapper methods for error-handling + // + + PropertiesPtr GetProperties ( ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_Properties ( + struct Properties * * ppvObject ) = 0; +}; + +struct __declspec(uuid("00000504-0000-0010-8000-00aa006d2ea4")) +Properties : _Collection +{ + // + // Property data + // + + __declspec(property(get=GetItem)) + PropertyPtr Item[]; + + // + // Wrapper methods for error-handling + // + + PropertyPtr GetItem ( + const _variant_t & Index ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_Item ( + VARIANT Index, + struct Property * * ppvObject ) = 0; +}; + +struct __declspec(uuid("00000503-0000-0010-8000-00aa006d2ea4")) +Property : IDispatch +{ + // + // Property data + // + + __declspec(property(get=GetValue,put=PutValue)) + _variant_t Value; + __declspec(property(get=GetName)) + _bstr_t Name; + __declspec(property(get=GetType)) + enum DataTypeEnum Type; + __declspec(property(get=GetAttributes,put=PutAttributes)) + long Attributes; + + // + // Wrapper methods for error-handling + // + + _variant_t GetValue ( ); + void PutValue ( + const _variant_t & pval ); + _bstr_t GetName ( ); + enum DataTypeEnum GetType ( ); + long GetAttributes ( ); + void PutAttributes ( + long plAttributes ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_Value ( + VARIANT * pval ) = 0; + virtual HRESULT __stdcall put_Value ( + VARIANT pval ) = 0; + virtual HRESULT __stdcall get_Name ( + BSTR * pbstr ) = 0; + virtual HRESULT __stdcall get_Type ( + enum DataTypeEnum * ptype ) = 0; + virtual HRESULT __stdcall get_Attributes ( + long * plAttributes ) = 0; + virtual HRESULT __stdcall put_Attributes ( + long plAttributes ) = 0; +}; + +struct __declspec(uuid("00000500-0000-0010-8000-00aa006d2ea4")) +Error : IDispatch +{ + // + // Property data + // + + __declspec(property(get=GetDescription)) + _bstr_t Description; + __declspec(property(get=GetNumber)) + long Number; + __declspec(property(get=GetSource)) + _bstr_t Source; + __declspec(property(get=GetHelpFile)) + _bstr_t HelpFile; + __declspec(property(get=GetHelpContext)) + long HelpContext; + __declspec(property(get=GetSQLState)) + _bstr_t SQLState; + __declspec(property(get=GetNativeError)) + long NativeError; + + // + // Wrapper methods for error-handling + // + + long GetNumber ( ); + _bstr_t GetSource ( ); + _bstr_t GetDescription ( ); + _bstr_t GetHelpFile ( ); + long GetHelpContext ( ); + _bstr_t GetSQLState ( ); + long GetNativeError ( ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_Number ( + long * pl ) = 0; + virtual HRESULT __stdcall get_Source ( + BSTR * pbstr ) = 0; + virtual HRESULT __stdcall get_Description ( + BSTR * pbstr ) = 0; + virtual HRESULT __stdcall get_HelpFile ( + BSTR * pbstr ) = 0; + virtual HRESULT __stdcall get_HelpContext ( + long * pl ) = 0; + virtual HRESULT __stdcall get_SQLState ( + BSTR * pbstr ) = 0; + virtual HRESULT __stdcall get_NativeError ( + long * pl ) = 0; +}; + +struct __declspec(uuid("00000501-0000-0010-8000-00aa006d2ea4")) +Errors : _Collection +{ + // + // Property data + // + + __declspec(property(get=GetItem)) + ErrorPtr Item[]; + + // + // Wrapper methods for error-handling + // + + ErrorPtr GetItem ( + const _variant_t & Index ); + HRESULT Clear ( ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_Item ( + VARIANT Index, + struct Error * * ppvObject ) = 0; + virtual HRESULT __stdcall raw_Clear ( ) = 0; +}; + +struct __declspec(uuid("00000508-0000-0010-8000-00aa006d2ea4")) +Command15 : _ADO +{ + // + // Property data + // + + __declspec(property(get=GetParameters)) + ParametersPtr Parameters; + __declspec(property(get=GetActiveConnection,put=PutRefActiveConnection)) + _ConnectionPtr ActiveConnection; + __declspec(property(get=GetCommandText,put=PutCommandText)) + _bstr_t CommandText; + __declspec(property(get=GetCommandTimeout,put=PutCommandTimeout)) + long CommandTimeout; + __declspec(property(get=GetPrepared,put=PutPrepared)) + VARIANT_BOOL Prepared; + __declspec(property(get=GetCommandType,put=PutCommandType)) + enum CommandTypeEnum CommandType; + __declspec(property(get=GetName,put=PutName)) + _bstr_t Name; + + // + // Wrapper methods for error-handling + // + + _ConnectionPtr GetActiveConnection ( ); + void PutRefActiveConnection ( + struct _Connection * ppvObject ); + void PutActiveConnection ( + const _variant_t & ppvObject ); + _bstr_t GetCommandText ( ); + void PutCommandText ( + _bstr_t pbstr ); + long GetCommandTimeout ( ); + void PutCommandTimeout ( + long pl ); + VARIANT_BOOL GetPrepared ( ); + void PutPrepared ( + VARIANT_BOOL pfPrepared ); + _RecordsetPtr Execute ( + VARIANT * RecordsAffected, + VARIANT * Parameters, + long Options ); + _ParameterPtr CreateParameter ( + _bstr_t Name, + enum DataTypeEnum Type, + enum ParameterDirectionEnum Direction, + long Size, + const _variant_t & Value = vtMissing ); + ParametersPtr GetParameters ( ); + void PutCommandType ( + enum CommandTypeEnum plCmdType ); + enum CommandTypeEnum GetCommandType ( ); + _bstr_t GetName ( ); + void PutName ( + _bstr_t pbstrName ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_ActiveConnection ( + struct _Connection * * ppvObject ) = 0; + virtual HRESULT __stdcall putref_ActiveConnection ( + struct _Connection * ppvObject ) = 0; + virtual HRESULT __stdcall put_ActiveConnection ( + VARIANT ppvObject ) = 0; + virtual HRESULT __stdcall get_CommandText ( + BSTR * pbstr ) = 0; + virtual HRESULT __stdcall put_CommandText ( + BSTR pbstr ) = 0; + virtual HRESULT __stdcall get_CommandTimeout ( + long * pl ) = 0; + virtual HRESULT __stdcall put_CommandTimeout ( + long pl ) = 0; + virtual HRESULT __stdcall get_Prepared ( + VARIANT_BOOL * pfPrepared ) = 0; + virtual HRESULT __stdcall put_Prepared ( + VARIANT_BOOL pfPrepared ) = 0; + virtual HRESULT __stdcall raw_Execute ( + VARIANT * RecordsAffected, + VARIANT * Parameters, + long Options, + struct _Recordset * * ppiRs ) = 0; + virtual HRESULT __stdcall raw_CreateParameter ( + BSTR Name, + enum DataTypeEnum Type, + enum ParameterDirectionEnum Direction, + long Size, + VARIANT Value, + struct _Parameter * * ppiprm ) = 0; + virtual HRESULT __stdcall get_Parameters ( + struct Parameters * * ppvObject ) = 0; + virtual HRESULT __stdcall put_CommandType ( + enum CommandTypeEnum plCmdType ) = 0; + virtual HRESULT __stdcall get_CommandType ( + enum CommandTypeEnum * plCmdType ) = 0; + virtual HRESULT __stdcall get_Name ( + BSTR * pbstrName ) = 0; + virtual HRESULT __stdcall put_Name ( + BSTR pbstrName ) = 0; +}; + +struct __declspec(uuid("00000515-0000-0010-8000-00aa006d2ea4")) +Connection15 : _ADO +{ + // + // Property data + // + + __declspec(property(get=GetConnectionString,put=PutConnectionString)) + _bstr_t ConnectionString; + __declspec(property(get=GetCommandTimeout,put=PutCommandTimeout)) + long CommandTimeout; + __declspec(property(get=GetConnectionTimeout,put=PutConnectionTimeout)) + long ConnectionTimeout; + __declspec(property(get=GetVersion)) + _bstr_t Version; + __declspec(property(get=GetErrors)) + ErrorsPtr Errors; + __declspec(property(get=GetDefaultDatabase,put=PutDefaultDatabase)) + _bstr_t DefaultDatabase; + __declspec(property(get=GetIsolationLevel,put=PutIsolationLevel)) + enum IsolationLevelEnum IsolationLevel; + __declspec(property(get=GetAttributes,put=PutAttributes)) + long Attributes; + __declspec(property(get=GetCursorLocation,put=PutCursorLocation)) + enum CursorLocationEnum CursorLocation; + __declspec(property(get=GetMode,put=PutMode)) + enum ConnectModeEnum Mode; + __declspec(property(get=GetProvider,put=PutProvider)) + _bstr_t Provider; + __declspec(property(get=GetState)) + long State; + + // + // Wrapper methods for error-handling + // + + _bstr_t GetConnectionString ( ); + void PutConnectionString ( + _bstr_t pbstr ); + long GetCommandTimeout ( ); + void PutCommandTimeout ( + long plTimeout ); + long GetConnectionTimeout ( ); + void PutConnectionTimeout ( + long plTimeout ); + _bstr_t GetVersion ( ); + HRESULT Close ( ); + _RecordsetPtr Execute ( + _bstr_t CommandText, + VARIANT * RecordsAffected, + long Options ); + long BeginTrans ( ); + HRESULT CommitTrans ( ); + HRESULT RollbackTrans ( ); + HRESULT Open ( + _bstr_t ConnectionString, + _bstr_t UserID, + _bstr_t Password, + long Options ); + ErrorsPtr GetErrors ( ); + _bstr_t GetDefaultDatabase ( ); + void PutDefaultDatabase ( + _bstr_t pbstr ); + enum IsolationLevelEnum GetIsolationLevel ( ); + void PutIsolationLevel ( + enum IsolationLevelEnum Level ); + long GetAttributes ( ); + void PutAttributes ( + long plAttr ); + enum CursorLocationEnum GetCursorLocation ( ); + void PutCursorLocation ( + enum CursorLocationEnum plCursorLoc ); + enum ConnectModeEnum GetMode ( ); + void PutMode ( + enum ConnectModeEnum plMode ); + _bstr_t GetProvider ( ); + void PutProvider ( + _bstr_t pbstr ); + long GetState ( ); + _RecordsetPtr OpenSchema ( + enum SchemaEnum Schema, + const _variant_t & Restrictions = vtMissing, + const _variant_t & SchemaID = vtMissing ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_ConnectionString ( + BSTR * pbstr ) = 0; + virtual HRESULT __stdcall put_ConnectionString ( + BSTR pbstr ) = 0; + virtual HRESULT __stdcall get_CommandTimeout ( + long * plTimeout ) = 0; + virtual HRESULT __stdcall put_CommandTimeout ( + long plTimeout ) = 0; + virtual HRESULT __stdcall get_ConnectionTimeout ( + long * plTimeout ) = 0; + virtual HRESULT __stdcall put_ConnectionTimeout ( + long plTimeout ) = 0; + virtual HRESULT __stdcall get_Version ( + BSTR * pbstr ) = 0; + virtual HRESULT __stdcall raw_Close ( ) = 0; + virtual HRESULT __stdcall raw_Execute ( + BSTR CommandText, + VARIANT * RecordsAffected, + long Options, + struct _Recordset * * ppiRset ) = 0; + virtual HRESULT __stdcall raw_BeginTrans ( + long * TransactionLevel ) = 0; + virtual HRESULT __stdcall raw_CommitTrans ( ) = 0; + virtual HRESULT __stdcall raw_RollbackTrans ( ) = 0; + virtual HRESULT __stdcall raw_Open ( + BSTR ConnectionString, + BSTR UserID, + BSTR Password, + long Options ) = 0; + virtual HRESULT __stdcall get_Errors ( + struct Errors * * ppvObject ) = 0; + virtual HRESULT __stdcall get_DefaultDatabase ( + BSTR * pbstr ) = 0; + virtual HRESULT __stdcall put_DefaultDatabase ( + BSTR pbstr ) = 0; + virtual HRESULT __stdcall get_IsolationLevel ( + enum IsolationLevelEnum * Level ) = 0; + virtual HRESULT __stdcall put_IsolationLevel ( + enum IsolationLevelEnum Level ) = 0; + virtual HRESULT __stdcall get_Attributes ( + long * plAttr ) = 0; + virtual HRESULT __stdcall put_Attributes ( + long plAttr ) = 0; + virtual HRESULT __stdcall get_CursorLocation ( + enum CursorLocationEnum * plCursorLoc ) = 0; + virtual HRESULT __stdcall put_CursorLocation ( + enum CursorLocationEnum plCursorLoc ) = 0; + virtual HRESULT __stdcall get_Mode ( + enum ConnectModeEnum * plMode ) = 0; + virtual HRESULT __stdcall put_Mode ( + enum ConnectModeEnum plMode ) = 0; + virtual HRESULT __stdcall get_Provider ( + BSTR * pbstr ) = 0; + virtual HRESULT __stdcall put_Provider ( + BSTR pbstr ) = 0; + virtual HRESULT __stdcall get_State ( + long * plObjState ) = 0; + virtual HRESULT __stdcall raw_OpenSchema ( + enum SchemaEnum Schema, + VARIANT Restrictions, + VARIANT SchemaID, + struct _Recordset * * pprset ) = 0; +}; + +struct __declspec(uuid("00000550-0000-0010-8000-00aa006d2ea4")) +_Connection : Connection15 +{ + // + // Wrapper methods for error-handling + // + + HRESULT Cancel ( ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall raw_Cancel ( ) = 0; +}; + +struct __declspec(uuid("0000050e-0000-0010-8000-00aa006d2ea4")) +Recordset15 : _ADO +{ + // + // Property data + // + + __declspec(property(get=GetFields)) + FieldsPtr Fields; + __declspec(property(get=GetPageSize,put=PutPageSize)) + long PageSize; + __declspec(property(get=GetPageCount)) + long PageCount; + __declspec(property(get=GetCursorLocation,put=PutCursorLocation)) + enum CursorLocationEnum CursorLocation; + __declspec(property(get=GetState)) + long State; + __declspec(property(get=GetMarshalOptions,put=PutMarshalOptions)) + enum MarshalOptionsEnum MarshalOptions; + __declspec(property(get=GetCollect,put=PutCollect)) + _variant_t Collect[]; + __declspec(property(get=GetEditMode)) + enum EditModeEnum EditMode; + __declspec(property(get=GetStatus)) + long Status; + __declspec(property(get=GetFilter,put=PutFilter)) + _variant_t Filter; + __declspec(property(get=GetSort,put=PutSort)) + _bstr_t Sort; + __declspec(property(get=GetAbsolutePosition,put=PutAbsolutePosition)) + enum PositionEnum AbsolutePosition; + __declspec(property(get=GetBOF)) + VARIANT_BOOL BOF; + __declspec(property(get=GetBookmark,put=PutBookmark)) + _variant_t Bookmark; + __declspec(property(get=GetCacheSize,put=PutCacheSize)) + long CacheSize; + __declspec(property(get=GetCursorType,put=PutCursorType)) + enum CursorTypeEnum CursorType; + __declspec(property(get=GetadoEOF)) + VARIANT_BOOL adoEOF; + __declspec(property(get=GetAbsolutePage,put=PutAbsolutePage)) + enum PositionEnum AbsolutePage; + __declspec(property(get=GetLockType,put=PutLockType)) + enum LockTypeEnum LockType; + __declspec(property(get=GetMaxRecords,put=PutMaxRecords)) + long MaxRecords; + __declspec(property(get=GetRecordCount)) + long RecordCount; + + // + // Wrapper methods for error-handling + // + + enum PositionEnum GetAbsolutePosition ( ); + void PutAbsolutePosition ( + enum PositionEnum pl ); + void PutRefActiveConnection ( + IDispatch * pvar ); + void PutActiveConnection ( + const _variant_t & pvar ); + _variant_t GetActiveConnection ( ); + VARIANT_BOOL GetBOF ( ); + _variant_t GetBookmark ( ); + void PutBookmark ( + const _variant_t & pvBookmark ); + long GetCacheSize ( ); + void PutCacheSize ( + long pl ); + enum CursorTypeEnum GetCursorType ( ); + void PutCursorType ( + enum CursorTypeEnum plCursorType ); + VARIANT_BOOL GetadoEOF ( ); + FieldsPtr GetFields ( ); + enum LockTypeEnum GetLockType ( ); + void PutLockType ( + enum LockTypeEnum plLockType ); + long GetMaxRecords ( ); + void PutMaxRecords ( + long plMaxRecords ); + long GetRecordCount ( ); + void PutRefSource ( + IDispatch * pvSource ); + void PutSource ( + _bstr_t pvSource ); + _variant_t GetSource ( ); + HRESULT AddNew ( + const _variant_t & FieldList = vtMissing, + const _variant_t & Values = vtMissing ); + HRESULT CancelUpdate ( ); + HRESULT Close ( ); + HRESULT Delete ( + enum AffectEnum AffectRecords ); + _variant_t GetRows ( + long Rows, + const _variant_t & Start = vtMissing, + const _variant_t & Fields = vtMissing ); + HRESULT Move ( + long NumRecords, + const _variant_t & Start = vtMissing ); + HRESULT MoveNext ( ); + HRESULT MovePrevious ( ); + HRESULT MoveFirst ( ); + HRESULT MoveLast ( ); + HRESULT Open ( + const _variant_t & Source, + const _variant_t & ActiveConnection, + enum CursorTypeEnum CursorType, + enum LockTypeEnum LockType, + long Options ); + HRESULT Requery ( + long Options ); + HRESULT _xResync ( + enum AffectEnum AffectRecords ); + HRESULT Update ( + const _variant_t & Fields = vtMissing, + const _variant_t & Values = vtMissing ); + enum PositionEnum GetAbsolutePage ( ); + void PutAbsolutePage ( + enum PositionEnum pl ); + enum EditModeEnum GetEditMode ( ); + _variant_t GetFilter ( ); + void PutFilter ( + const _variant_t & Criteria ); + long GetPageCount ( ); + long GetPageSize ( ); + void PutPageSize ( + long pl ); + _bstr_t GetSort ( ); + void PutSort ( + _bstr_t Criteria ); + long GetStatus ( ); + long GetState ( ); + _RecordsetPtr _xClone ( ); + HRESULT UpdateBatch ( + enum AffectEnum AffectRecords ); + HRESULT CancelBatch ( + enum AffectEnum AffectRecords ); + enum CursorLocationEnum GetCursorLocation ( ); + void PutCursorLocation ( + enum CursorLocationEnum plCursorLoc ); + _RecordsetPtr NextRecordset ( + VARIANT * RecordsAffected ); + VARIANT_BOOL Supports ( + enum CursorOptionEnum CursorOptions ); + _variant_t GetCollect ( + const _variant_t & Index ); + void PutCollect ( + const _variant_t & Index, + const _variant_t & pvar ); + enum MarshalOptionsEnum GetMarshalOptions ( ); + void PutMarshalOptions ( + enum MarshalOptionsEnum peMarshal ); + HRESULT Find ( + _bstr_t Criteria, + long SkipRecords, + enum SearchDirectionEnum SearchDirection, + const _variant_t & Start = vtMissing ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_AbsolutePosition ( + enum PositionEnum * pl ) = 0; + virtual HRESULT __stdcall put_AbsolutePosition ( + enum PositionEnum pl ) = 0; + virtual HRESULT __stdcall putref_ActiveConnection ( + IDispatch * pvar ) = 0; + virtual HRESULT __stdcall put_ActiveConnection ( + VARIANT pvar ) = 0; + virtual HRESULT __stdcall get_ActiveConnection ( + VARIANT * pvar ) = 0; + virtual HRESULT __stdcall get_BOF ( + VARIANT_BOOL * pb ) = 0; + virtual HRESULT __stdcall get_Bookmark ( + VARIANT * pvBookmark ) = 0; + virtual HRESULT __stdcall put_Bookmark ( + VARIANT pvBookmark ) = 0; + virtual HRESULT __stdcall get_CacheSize ( + long * pl ) = 0; + virtual HRESULT __stdcall put_CacheSize ( + long pl ) = 0; + virtual HRESULT __stdcall get_CursorType ( + enum CursorTypeEnum * plCursorType ) = 0; + virtual HRESULT __stdcall put_CursorType ( + enum CursorTypeEnum plCursorType ) = 0; + virtual HRESULT __stdcall get_adoEOF ( + VARIANT_BOOL * pb ) = 0; + virtual HRESULT __stdcall get_Fields ( + struct Fields * * ppvObject ) = 0; + virtual HRESULT __stdcall get_LockType ( + enum LockTypeEnum * plLockType ) = 0; + virtual HRESULT __stdcall put_LockType ( + enum LockTypeEnum plLockType ) = 0; + virtual HRESULT __stdcall get_MaxRecords ( + long * plMaxRecords ) = 0; + virtual HRESULT __stdcall put_MaxRecords ( + long plMaxRecords ) = 0; + virtual HRESULT __stdcall get_RecordCount ( + long * pl ) = 0; + virtual HRESULT __stdcall putref_Source ( + IDispatch * pvSource ) = 0; + virtual HRESULT __stdcall put_Source ( + BSTR pvSource ) = 0; + virtual HRESULT __stdcall get_Source ( + VARIANT * pvSource ) = 0; + virtual HRESULT __stdcall raw_AddNew ( + VARIANT FieldList = vtMissing, + VARIANT Values = vtMissing ) = 0; + virtual HRESULT __stdcall raw_CancelUpdate ( ) = 0; + virtual HRESULT __stdcall raw_Close ( ) = 0; + virtual HRESULT __stdcall raw_Delete ( + enum AffectEnum AffectRecords ) = 0; + virtual HRESULT __stdcall raw_GetRows ( + long Rows, + VARIANT Start, + VARIANT Fields, + VARIANT * pvar ) = 0; + virtual HRESULT __stdcall raw_Move ( + long NumRecords, + VARIANT Start = vtMissing ) = 0; + virtual HRESULT __stdcall raw_MoveNext ( ) = 0; + virtual HRESULT __stdcall raw_MovePrevious ( ) = 0; + virtual HRESULT __stdcall raw_MoveFirst ( ) = 0; + virtual HRESULT __stdcall raw_MoveLast ( ) = 0; + virtual HRESULT __stdcall raw_Open ( + VARIANT Source, + VARIANT ActiveConnection, + enum CursorTypeEnum CursorType, + enum LockTypeEnum LockType, + long Options ) = 0; + virtual HRESULT __stdcall raw_Requery ( + long Options ) = 0; + virtual HRESULT __stdcall raw__xResync ( + enum AffectEnum AffectRecords ) = 0; + virtual HRESULT __stdcall raw_Update ( + VARIANT Fields = vtMissing, + VARIANT Values = vtMissing ) = 0; + virtual HRESULT __stdcall get_AbsolutePage ( + enum PositionEnum * pl ) = 0; + virtual HRESULT __stdcall put_AbsolutePage ( + enum PositionEnum pl ) = 0; + virtual HRESULT __stdcall get_EditMode ( + enum EditModeEnum * pl ) = 0; + virtual HRESULT __stdcall get_Filter ( + VARIANT * Criteria ) = 0; + virtual HRESULT __stdcall put_Filter ( + VARIANT Criteria ) = 0; + virtual HRESULT __stdcall get_PageCount ( + long * pl ) = 0; + virtual HRESULT __stdcall get_PageSize ( + long * pl ) = 0; + virtual HRESULT __stdcall put_PageSize ( + long pl ) = 0; + virtual HRESULT __stdcall get_Sort ( + BSTR * Criteria ) = 0; + virtual HRESULT __stdcall put_Sort ( + BSTR Criteria ) = 0; + virtual HRESULT __stdcall get_Status ( + long * pl ) = 0; + virtual HRESULT __stdcall get_State ( + long * plObjState ) = 0; + virtual HRESULT __stdcall raw__xClone ( + struct _Recordset * * ppvObject ) = 0; + virtual HRESULT __stdcall raw_UpdateBatch ( + enum AffectEnum AffectRecords ) = 0; + virtual HRESULT __stdcall raw_CancelBatch ( + enum AffectEnum AffectRecords ) = 0; + virtual HRESULT __stdcall get_CursorLocation ( + enum CursorLocationEnum * plCursorLoc ) = 0; + virtual HRESULT __stdcall put_CursorLocation ( + enum CursorLocationEnum plCursorLoc ) = 0; + virtual HRESULT __stdcall raw_NextRecordset ( + VARIANT * RecordsAffected, + struct _Recordset * * ppiRs ) = 0; + virtual HRESULT __stdcall raw_Supports ( + enum CursorOptionEnum CursorOptions, + VARIANT_BOOL * pb ) = 0; + virtual HRESULT __stdcall get_Collect ( + VARIANT Index, + VARIANT * pvar ) = 0; + virtual HRESULT __stdcall put_Collect ( + VARIANT Index, + VARIANT pvar ) = 0; + virtual HRESULT __stdcall get_MarshalOptions ( + enum MarshalOptionsEnum * peMarshal ) = 0; + virtual HRESULT __stdcall put_MarshalOptions ( + enum MarshalOptionsEnum peMarshal ) = 0; + virtual HRESULT __stdcall raw_Find ( + BSTR Criteria, + long SkipRecords, + enum SearchDirectionEnum SearchDirection, + VARIANT Start = vtMissing ) = 0; +}; + +struct __declspec(uuid("0000054f-0000-0010-8000-00aa006d2ea4")) +Recordset20 : Recordset15 +{ + // + // Property data + // + + __declspec(property(get=GetDataSource,put=PutRefDataSource)) + IUnknownPtr DataSource; + __declspec(property(get=GetActiveCommand)) + IDispatchPtr ActiveCommand; + __declspec(property(get=GetStayInSync,put=PutStayInSync)) + VARIANT_BOOL StayInSync; + __declspec(property(get=GetDataMember,put=PutDataMember)) + _bstr_t DataMember; + + // + // Wrapper methods for error-handling + // + + HRESULT Cancel ( ); + IUnknownPtr GetDataSource ( ); + void PutRefDataSource ( + IUnknown * ppunkDataSource ); + HRESULT _xSave ( + _bstr_t FileName, + enum PersistFormatEnum PersistFormat ); + IDispatchPtr GetActiveCommand ( ); + void PutStayInSync ( + VARIANT_BOOL pbStayInSync ); + VARIANT_BOOL GetStayInSync ( ); + _bstr_t GetString ( + enum StringFormatEnum StringFormat, + long NumRows, + _bstr_t ColumnDelimeter, + _bstr_t RowDelimeter, + _bstr_t NullExpr ); + _bstr_t GetDataMember ( ); + void PutDataMember ( + _bstr_t pbstrDataMember ); + enum CompareEnum CompareBookmarks ( + const _variant_t & Bookmark1, + const _variant_t & Bookmark2 ); + _RecordsetPtr Clone ( + enum LockTypeEnum LockType ); + HRESULT Resync ( + enum AffectEnum AffectRecords, + enum ResyncEnum ResyncValues ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall raw_Cancel ( ) = 0; + virtual HRESULT __stdcall get_DataSource ( + IUnknown * * ppunkDataSource ) = 0; + virtual HRESULT __stdcall putref_DataSource ( + IUnknown * ppunkDataSource ) = 0; + virtual HRESULT __stdcall raw__xSave ( + BSTR FileName, + enum PersistFormatEnum PersistFormat ) = 0; + virtual HRESULT __stdcall get_ActiveCommand ( + IDispatch * * ppCmd ) = 0; + virtual HRESULT __stdcall put_StayInSync ( + VARIANT_BOOL pbStayInSync ) = 0; + virtual HRESULT __stdcall get_StayInSync ( + VARIANT_BOOL * pbStayInSync ) = 0; + virtual HRESULT __stdcall raw_GetString ( + enum StringFormatEnum StringFormat, + long NumRows, + BSTR ColumnDelimeter, + BSTR RowDelimeter, + BSTR NullExpr, + BSTR * pRetString ) = 0; + virtual HRESULT __stdcall get_DataMember ( + BSTR * pbstrDataMember ) = 0; + virtual HRESULT __stdcall put_DataMember ( + BSTR pbstrDataMember ) = 0; + virtual HRESULT __stdcall raw_CompareBookmarks ( + VARIANT Bookmark1, + VARIANT Bookmark2, + enum CompareEnum * pCompare ) = 0; + virtual HRESULT __stdcall raw_Clone ( + enum LockTypeEnum LockType, + struct _Recordset * * ppvObject ) = 0; + virtual HRESULT __stdcall raw_Resync ( + enum AffectEnum AffectRecords, + enum ResyncEnum ResyncValues ) = 0; +}; + +struct __declspec(uuid("00000555-0000-0010-8000-00aa006d2ea4")) +Recordset21 : Recordset20 +{ + // + // Property data + // + + __declspec(property(get=GetIndex,put=PutIndex)) + _bstr_t Index; + + // + // Wrapper methods for error-handling + // + + HRESULT Seek ( + const _variant_t & KeyValues, + enum SeekEnum SeekOption ); + void PutIndex ( + _bstr_t pbstrIndex ); + _bstr_t GetIndex ( ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall raw_Seek ( + VARIANT KeyValues, + enum SeekEnum SeekOption ) = 0; + virtual HRESULT __stdcall put_Index ( + BSTR pbstrIndex ) = 0; + virtual HRESULT __stdcall get_Index ( + BSTR * pbstrIndex ) = 0; +}; + +struct __declspec(uuid("00000556-0000-0010-8000-00aa006d2ea4")) +_Recordset : Recordset21 +{ + // + // Wrapper methods for error-handling + // + + HRESULT Save ( + const _variant_t & Destination, + enum PersistFormatEnum PersistFormat ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall raw_Save ( + VARIANT Destination, + enum PersistFormatEnum PersistFormat ) = 0; +}; + +struct __declspec(uuid("00000506-0000-0010-8000-00aa006d2ea4")) +Fields15 : _Collection +{ + // + // Property data + // + + __declspec(property(get=GetItem)) + FieldPtr Item[]; + + // + // Wrapper methods for error-handling + // + + FieldPtr GetItem ( + const _variant_t & Index ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_Item ( + VARIANT Index, + struct Field * * ppvObject ) = 0; +}; + +struct __declspec(uuid("0000054d-0000-0010-8000-00aa006d2ea4")) +Fields20 : Fields15 +{ + // + // Wrapper methods for error-handling + // + + HRESULT _Append ( + _bstr_t Name, + enum DataTypeEnum Type, + long DefinedSize, + enum FieldAttributeEnum Attrib ); + HRESULT Delete ( + const _variant_t & Index ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall raw__Append ( + BSTR Name, + enum DataTypeEnum Type, + long DefinedSize, + enum FieldAttributeEnum Attrib ) = 0; + virtual HRESULT __stdcall raw_Delete ( + VARIANT Index ) = 0; +}; + +struct __declspec(uuid("00000564-0000-0010-8000-00aa006d2ea4")) +Fields : Fields20 +{ + // + // Wrapper methods for error-handling + // + + HRESULT Append ( + _bstr_t Name, + enum DataTypeEnum Type, + long DefinedSize, + enum FieldAttributeEnum Attrib, + const _variant_t & FieldValue = vtMissing ); + HRESULT Update ( ); + HRESULT Resync ( + enum ResyncEnum ResyncValues ); + HRESULT CancelUpdate ( ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall raw_Append ( + BSTR Name, + enum DataTypeEnum Type, + long DefinedSize, + enum FieldAttributeEnum Attrib, + VARIANT FieldValue = vtMissing ) = 0; + virtual HRESULT __stdcall raw_Update ( ) = 0; + virtual HRESULT __stdcall raw_Resync ( + enum ResyncEnum ResyncValues ) = 0; + virtual HRESULT __stdcall raw_CancelUpdate ( ) = 0; +}; + +struct __declspec(uuid("0000054c-0000-0010-8000-00aa006d2ea4")) +Field20 : _ADO +{ + // + // Property data + // + + __declspec(property(get=GetValue,put=PutValue)) + _variant_t Value; + __declspec(property(get=GetName)) + _bstr_t Name; + __declspec(property(get=GetType,put=PutType)) + enum DataTypeEnum Type; + __declspec(property(get=GetDefinedSize,put=PutDefinedSize)) + long DefinedSize; + __declspec(property(get=GetOriginalValue)) + _variant_t OriginalValue; + __declspec(property(get=GetUnderlyingValue)) + _variant_t UnderlyingValue; + __declspec(property(get=GetActualSize)) + long ActualSize; + __declspec(property(get=GetPrecision,put=PutPrecision)) + unsigned char Precision; + __declspec(property(get=GetNumericScale,put=PutNumericScale)) + unsigned char NumericScale; + __declspec(property(get=GetAttributes,put=PutAttributes)) + long Attributes; + __declspec(property(get=GetDataFormat,put=PutRefDataFormat)) + IUnknownPtr DataFormat; + + // + // Wrapper methods for error-handling + // + + long GetActualSize ( ); + long GetAttributes ( ); + long GetDefinedSize ( ); + _bstr_t GetName ( ); + enum DataTypeEnum GetType ( ); + _variant_t GetValue ( ); + void PutValue ( + const _variant_t & pvar ); + unsigned char GetPrecision ( ); + unsigned char GetNumericScale ( ); + HRESULT AppendChunk ( + const _variant_t & Data ); + _variant_t GetChunk ( + long Length ); + _variant_t GetOriginalValue ( ); + _variant_t GetUnderlyingValue ( ); + IUnknownPtr GetDataFormat ( ); + void PutRefDataFormat ( + IUnknown * ppiDF ); + void PutPrecision ( + unsigned char pbPrecision ); + void PutNumericScale ( + unsigned char pbNumericScale ); + void PutType ( + enum DataTypeEnum pDataType ); + void PutDefinedSize ( + long pl ); + void PutAttributes ( + long pl ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_ActualSize ( + long * pl ) = 0; + virtual HRESULT __stdcall get_Attributes ( + long * pl ) = 0; + virtual HRESULT __stdcall get_DefinedSize ( + long * pl ) = 0; + virtual HRESULT __stdcall get_Name ( + BSTR * pbstr ) = 0; + virtual HRESULT __stdcall get_Type ( + enum DataTypeEnum * pDataType ) = 0; + virtual HRESULT __stdcall get_Value ( + VARIANT * pvar ) = 0; + virtual HRESULT __stdcall put_Value ( + VARIANT pvar ) = 0; + virtual HRESULT __stdcall get_Precision ( + unsigned char * pbPrecision ) = 0; + virtual HRESULT __stdcall get_NumericScale ( + unsigned char * pbNumericScale ) = 0; + virtual HRESULT __stdcall raw_AppendChunk ( + VARIANT Data ) = 0; + virtual HRESULT __stdcall raw_GetChunk ( + long Length, + VARIANT * pvar ) = 0; + virtual HRESULT __stdcall get_OriginalValue ( + VARIANT * pvar ) = 0; + virtual HRESULT __stdcall get_UnderlyingValue ( + VARIANT * pvar ) = 0; + virtual HRESULT __stdcall get_DataFormat ( + IUnknown * * ppiDF ) = 0; + virtual HRESULT __stdcall putref_DataFormat ( + IUnknown * ppiDF ) = 0; + virtual HRESULT __stdcall put_Precision ( + unsigned char pbPrecision ) = 0; + virtual HRESULT __stdcall put_NumericScale ( + unsigned char pbNumericScale ) = 0; + virtual HRESULT __stdcall put_Type ( + enum DataTypeEnum pDataType ) = 0; + virtual HRESULT __stdcall put_DefinedSize ( + long pl ) = 0; + virtual HRESULT __stdcall put_Attributes ( + long pl ) = 0; +}; + +struct __declspec(uuid("00000569-0000-0010-8000-00aa006d2ea4")) +Field : Field20 +{ + // + // Property data + // + + __declspec(property(get=GetStatus)) + long Status; + + // + // Wrapper methods for error-handling + // + + long GetStatus ( ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_Status ( + long * pFStatus ) = 0; +}; + +struct __declspec(uuid("0000050c-0000-0010-8000-00aa006d2ea4")) +_Parameter : _ADO +{ + // + // Property data + // + + __declspec(property(get=GetValue,put=PutValue)) + _variant_t Value; + __declspec(property(get=GetName,put=PutName)) + _bstr_t Name; + __declspec(property(get=GetType,put=PutType)) + enum DataTypeEnum Type; + __declspec(property(get=GetDirection,put=PutDirection)) + enum ParameterDirectionEnum Direction; + __declspec(property(get=GetPrecision,put=PutPrecision)) + unsigned char Precision; + __declspec(property(get=GetNumericScale,put=PutNumericScale)) + unsigned char NumericScale; + __declspec(property(get=GetSize,put=PutSize)) + long Size; + __declspec(property(get=GetAttributes,put=PutAttributes)) + long Attributes; + + // + // Wrapper methods for error-handling + // + + _bstr_t GetName ( ); + void PutName ( + _bstr_t pbstr ); + _variant_t GetValue ( ); + void PutValue ( + const _variant_t & pvar ); + enum DataTypeEnum GetType ( ); + void PutType ( + enum DataTypeEnum psDataType ); + void PutDirection ( + enum ParameterDirectionEnum plParmDirection ); + enum ParameterDirectionEnum GetDirection ( ); + void PutPrecision ( + unsigned char pbPrecision ); + unsigned char GetPrecision ( ); + void PutNumericScale ( + unsigned char pbScale ); + unsigned char GetNumericScale ( ); + void PutSize ( + long pl ); + long GetSize ( ); + HRESULT AppendChunk ( + const _variant_t & Val ); + long GetAttributes ( ); + void PutAttributes ( + long plParmAttribs ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_Name ( + BSTR * pbstr ) = 0; + virtual HRESULT __stdcall put_Name ( + BSTR pbstr ) = 0; + virtual HRESULT __stdcall get_Value ( + VARIANT * pvar ) = 0; + virtual HRESULT __stdcall put_Value ( + VARIANT pvar ) = 0; + virtual HRESULT __stdcall get_Type ( + enum DataTypeEnum * psDataType ) = 0; + virtual HRESULT __stdcall put_Type ( + enum DataTypeEnum psDataType ) = 0; + virtual HRESULT __stdcall put_Direction ( + enum ParameterDirectionEnum plParmDirection ) = 0; + virtual HRESULT __stdcall get_Direction ( + enum ParameterDirectionEnum * plParmDirection ) = 0; + virtual HRESULT __stdcall put_Precision ( + unsigned char pbPrecision ) = 0; + virtual HRESULT __stdcall get_Precision ( + unsigned char * pbPrecision ) = 0; + virtual HRESULT __stdcall put_NumericScale ( + unsigned char pbScale ) = 0; + virtual HRESULT __stdcall get_NumericScale ( + unsigned char * pbScale ) = 0; + virtual HRESULT __stdcall put_Size ( + long pl ) = 0; + virtual HRESULT __stdcall get_Size ( + long * pl ) = 0; + virtual HRESULT __stdcall raw_AppendChunk ( + VARIANT Val ) = 0; + virtual HRESULT __stdcall get_Attributes ( + long * plParmAttribs ) = 0; + virtual HRESULT __stdcall put_Attributes ( + long plParmAttribs ) = 0; +}; + +struct __declspec(uuid("0000050d-0000-0010-8000-00aa006d2ea4")) +Parameters : _DynaCollection +{ + // + // Property data + // + + __declspec(property(get=GetItem)) + _ParameterPtr Item[]; + + // + // Wrapper methods for error-handling + // + + _ParameterPtr GetItem ( + const _variant_t & Index ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_Item ( + VARIANT Index, + struct _Parameter * * ppvObject ) = 0; +}; + +struct __declspec(uuid("0000054e-0000-0010-8000-00aa006d2ea4")) +_Command : Command15 +{ + // + // Property data + // + + __declspec(property(get=GetState)) + long State; + + // + // Wrapper methods for error-handling + // + + long GetState ( ); + HRESULT Cancel ( ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_State ( + long * plObjState ) = 0; + virtual HRESULT __stdcall raw_Cancel ( ) = 0; +}; + +struct __declspec(uuid("00000402-0000-0010-8000-00aa006d2ea4")) +ConnectionEventsVt : IUnknown +{ + // + // Wrapper methods for error-handling + // + + HRESULT InfoMessage ( + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ); + HRESULT BeginTransComplete ( + long TransactionLevel, + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ); + HRESULT CommitTransComplete ( + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ); + HRESULT RollbackTransComplete ( + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ); + HRESULT WillExecute ( + BSTR * Source, + enum CursorTypeEnum * CursorType, + enum LockTypeEnum * LockType, + long * Options, + enum EventStatusEnum * adStatus, + struct _Command * pCommand, + struct _Recordset * pRecordset, + struct _Connection * pConnection ); + HRESULT ExecuteComplete ( + long RecordsAffected, + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Command * pCommand, + struct _Recordset * pRecordset, + struct _Connection * pConnection ); + HRESULT WillConnect ( + BSTR * ConnectionString, + BSTR * UserID, + BSTR * Password, + long * Options, + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ); + HRESULT ConnectComplete ( + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ); + HRESULT Disconnect ( + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall raw_InfoMessage ( + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ) = 0; + virtual HRESULT __stdcall raw_BeginTransComplete ( + long TransactionLevel, + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ) = 0; + virtual HRESULT __stdcall raw_CommitTransComplete ( + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ) = 0; + virtual HRESULT __stdcall raw_RollbackTransComplete ( + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ) = 0; + virtual HRESULT __stdcall raw_WillExecute ( + BSTR * Source, + enum CursorTypeEnum * CursorType, + enum LockTypeEnum * LockType, + long * Options, + enum EventStatusEnum * adStatus, + struct _Command * pCommand, + struct _Recordset * pRecordset, + struct _Connection * pConnection ) = 0; + virtual HRESULT __stdcall raw_ExecuteComplete ( + long RecordsAffected, + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Command * pCommand, + struct _Recordset * pRecordset, + struct _Connection * pConnection ) = 0; + virtual HRESULT __stdcall raw_WillConnect ( + BSTR * ConnectionString, + BSTR * UserID, + BSTR * Password, + long * Options, + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ) = 0; + virtual HRESULT __stdcall raw_ConnectComplete ( + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ) = 0; + virtual HRESULT __stdcall raw_Disconnect ( + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ) = 0; +}; + +struct __declspec(uuid("00000403-0000-0010-8000-00aa006d2ea4")) +RecordsetEventsVt : IUnknown +{ + // + // Wrapper methods for error-handling + // + + HRESULT WillChangeField ( + long cFields, + const _variant_t & Fields, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT FieldChangeComplete ( + long cFields, + const _variant_t & Fields, + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT WillChangeRecord ( + enum EventReasonEnum adReason, + long cRecords, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT RecordChangeComplete ( + enum EventReasonEnum adReason, + long cRecords, + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT WillChangeRecordset ( + enum EventReasonEnum adReason, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT RecordsetChangeComplete ( + enum EventReasonEnum adReason, + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT WillMove ( + enum EventReasonEnum adReason, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT MoveComplete ( + enum EventReasonEnum adReason, + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT EndOfRecordset ( + VARIANT_BOOL * fMoreData, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT FetchProgress ( + long Progress, + long MaxProgress, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT FetchComplete ( + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall raw_WillChangeField ( + long cFields, + VARIANT Fields, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ) = 0; + virtual HRESULT __stdcall raw_FieldChangeComplete ( + long cFields, + VARIANT Fields, + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ) = 0; + virtual HRESULT __stdcall raw_WillChangeRecord ( + enum EventReasonEnum adReason, + long cRecords, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ) = 0; + virtual HRESULT __stdcall raw_RecordChangeComplete ( + enum EventReasonEnum adReason, + long cRecords, + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ) = 0; + virtual HRESULT __stdcall raw_WillChangeRecordset ( + enum EventReasonEnum adReason, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ) = 0; + virtual HRESULT __stdcall raw_RecordsetChangeComplete ( + enum EventReasonEnum adReason, + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ) = 0; + virtual HRESULT __stdcall raw_WillMove ( + enum EventReasonEnum adReason, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ) = 0; + virtual HRESULT __stdcall raw_MoveComplete ( + enum EventReasonEnum adReason, + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ) = 0; + virtual HRESULT __stdcall raw_EndOfRecordset ( + VARIANT_BOOL * fMoreData, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ) = 0; + virtual HRESULT __stdcall raw_FetchProgress ( + long Progress, + long MaxProgress, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ) = 0; + virtual HRESULT __stdcall raw_FetchComplete ( + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ) = 0; +}; + +struct __declspec(uuid("00000400-0000-0010-8000-00aa006d2ea4")) +ConnectionEvents : IDispatch +{ + // + // Wrapper methods for error-handling + // + + // Methods: + HRESULT InfoMessage ( + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ); + HRESULT BeginTransComplete ( + long TransactionLevel, + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ); + HRESULT CommitTransComplete ( + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ); + HRESULT RollbackTransComplete ( + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ); + HRESULT WillExecute ( + BSTR * Source, + enum CursorTypeEnum * CursorType, + enum LockTypeEnum * LockType, + long * Options, + enum EventStatusEnum * adStatus, + struct _Command * pCommand, + struct _Recordset * pRecordset, + struct _Connection * pConnection ); + HRESULT ExecuteComplete ( + long RecordsAffected, + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Command * pCommand, + struct _Recordset * pRecordset, + struct _Connection * pConnection ); + HRESULT WillConnect ( + BSTR * ConnectionString, + BSTR * UserID, + BSTR * Password, + long * Options, + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ); + HRESULT ConnectComplete ( + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ); + HRESULT Disconnect ( + enum EventStatusEnum * adStatus, + struct _Connection * pConnection ); +}; + +struct __declspec(uuid("00000266-0000-0010-8000-00aa006d2ea4")) +RecordsetEvents : IDispatch +{ + // + // Wrapper methods for error-handling + // + + // Methods: + HRESULT WillChangeField ( + long cFields, + const _variant_t & Fields, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT FieldChangeComplete ( + long cFields, + const _variant_t & Fields, + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT WillChangeRecord ( + enum EventReasonEnum adReason, + long cRecords, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT RecordChangeComplete ( + enum EventReasonEnum adReason, + long cRecords, + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT WillChangeRecordset ( + enum EventReasonEnum adReason, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT RecordsetChangeComplete ( + enum EventReasonEnum adReason, + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT WillMove ( + enum EventReasonEnum adReason, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT MoveComplete ( + enum EventReasonEnum adReason, + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT EndOfRecordset ( + VARIANT_BOOL * fMoreData, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT FetchProgress ( + long Progress, + long MaxProgress, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); + HRESULT FetchComplete ( + struct Error * pError, + enum EventStatusEnum * adStatus, + struct _Recordset * pRecordset ); +}; + +struct __declspec(uuid("00000516-0000-0010-8000-00aa006d2ea4")) +ADOConnectionConstruction15 : IUnknown +{ + // + // Property data + // + + __declspec(property(get=GetDSO)) + IUnknownPtr DSO; + __declspec(property(get=GetSession)) + IUnknownPtr Session; + + // + // Wrapper methods for error-handling + // + + IUnknownPtr GetDSO ( ); + IUnknownPtr GetSession ( ); + HRESULT WrapDSOandSession ( + IUnknown * pDSO, + IUnknown * pSession ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_DSO ( + IUnknown * * ppDSO ) = 0; + virtual HRESULT __stdcall get_Session ( + IUnknown * * ppSession ) = 0; + virtual HRESULT __stdcall raw_WrapDSOandSession ( + IUnknown * pDSO, + IUnknown * pSession ) = 0; +}; + +struct __declspec(uuid("00000551-0000-0010-8000-00aa006d2ea4")) +ADOConnectionConstruction : ADOConnectionConstruction15 +{}; + +struct __declspec(uuid("00000514-0000-0010-8000-00aa006d2ea4")) +Connection; + // [ default ] interface _Connection + // [ default, source ] dispinterface ConnectionEvents + +struct __declspec(uuid("00000562-0000-0010-8000-00aa006d2ea4")) +_Record : _ADO +{ + // + // Property data + // + + __declspec(property(get=GetFields)) + FieldsPtr Fields; + __declspec(property(get=GetState)) + enum ObjectStateEnum State; + __declspec(property(get=GetMode,put=PutMode)) + enum ConnectModeEnum Mode; + __declspec(property(get=GetParentURL)) + _bstr_t ParentURL; + __declspec(property(get=GetRecordType)) + enum RecordTypeEnum RecordType; + + // + // Wrapper methods for error-handling + // + + _variant_t GetActiveConnection ( ); + void PutActiveConnection ( + _bstr_t pvar ); + void PutRefActiveConnection ( + struct _Connection * pvar ); + enum ObjectStateEnum GetState ( ); + _variant_t GetSource ( ); + void PutSource ( + _bstr_t pvar ); + void PutRefSource ( + IDispatch * pvar ); + enum ConnectModeEnum GetMode ( ); + void PutMode ( + enum ConnectModeEnum pMode ); + _bstr_t GetParentURL ( ); + _bstr_t MoveRecord ( + _bstr_t Source, + _bstr_t Destination, + _bstr_t UserName, + _bstr_t Password, + enum MoveRecordOptionsEnum Options, + VARIANT_BOOL Async ); + _bstr_t CopyRecord ( + _bstr_t Source, + _bstr_t Destination, + _bstr_t UserName, + _bstr_t Password, + enum CopyRecordOptionsEnum Options, + VARIANT_BOOL Async ); + HRESULT DeleteRecord ( + _bstr_t Source, + VARIANT_BOOL Async ); + HRESULT Open ( + const _variant_t & Source, + const _variant_t & ActiveConnection, + enum ConnectModeEnum Mode, + enum RecordCreateOptionsEnum CreateOptions, + enum RecordOpenOptionsEnum Options, + _bstr_t UserName, + _bstr_t Password ); + HRESULT Close ( ); + FieldsPtr GetFields ( ); + enum RecordTypeEnum GetRecordType ( ); + _RecordsetPtr GetChildren ( ); + HRESULT Cancel ( ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_ActiveConnection ( + VARIANT * pvar ) = 0; + virtual HRESULT __stdcall put_ActiveConnection ( + BSTR pvar ) = 0; + virtual HRESULT __stdcall putref_ActiveConnection ( + struct _Connection * pvar ) = 0; + virtual HRESULT __stdcall get_State ( + enum ObjectStateEnum * pState ) = 0; + virtual HRESULT __stdcall get_Source ( + VARIANT * pvar ) = 0; + virtual HRESULT __stdcall put_Source ( + BSTR pvar ) = 0; + virtual HRESULT __stdcall putref_Source ( + IDispatch * pvar ) = 0; + virtual HRESULT __stdcall get_Mode ( + enum ConnectModeEnum * pMode ) = 0; + virtual HRESULT __stdcall put_Mode ( + enum ConnectModeEnum pMode ) = 0; + virtual HRESULT __stdcall get_ParentURL ( + BSTR * pbstrParentURL ) = 0; + virtual HRESULT __stdcall raw_MoveRecord ( + BSTR Source, + BSTR Destination, + BSTR UserName, + BSTR Password, + enum MoveRecordOptionsEnum Options, + VARIANT_BOOL Async, + BSTR * pbstrNewURL ) = 0; + virtual HRESULT __stdcall raw_CopyRecord ( + BSTR Source, + BSTR Destination, + BSTR UserName, + BSTR Password, + enum CopyRecordOptionsEnum Options, + VARIANT_BOOL Async, + BSTR * pbstrNewURL ) = 0; + virtual HRESULT __stdcall raw_DeleteRecord ( + BSTR Source, + VARIANT_BOOL Async ) = 0; + virtual HRESULT __stdcall raw_Open ( + VARIANT Source, + VARIANT ActiveConnection, + enum ConnectModeEnum Mode, + enum RecordCreateOptionsEnum CreateOptions, + enum RecordOpenOptionsEnum Options, + BSTR UserName, + BSTR Password ) = 0; + virtual HRESULT __stdcall raw_Close ( ) = 0; + virtual HRESULT __stdcall get_Fields ( + struct Fields * * ppFlds ) = 0; + virtual HRESULT __stdcall get_RecordType ( + enum RecordTypeEnum * ptype ) = 0; + virtual HRESULT __stdcall raw_GetChildren ( + struct _Recordset * * pprset ) = 0; + virtual HRESULT __stdcall raw_Cancel ( ) = 0; +}; + +struct __declspec(uuid("00000560-0000-0010-8000-00aa006d2ea4")) +Record; + // [ default ] interface _Record + +struct __declspec(uuid("00000563-0000-0010-8000-00aa006d2ea4")) +IRecFields : IUnknown +{ + // + // Wrapper methods for error-handling + // + + HRESULT ADOCheck ( ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall raw_ADOCheck ( ) = 0; +}; + +struct __declspec(uuid("00000565-0000-0010-8000-00aa006d2ea4")) +_Stream : IDispatch +{ + // + // Property data + // + + __declspec(property(get=GetSize)) + long Size; + __declspec(property(get=GetEOS)) + VARIANT_BOOL EOS; + __declspec(property(get=GetPosition,put=PutPosition)) + long Position; + __declspec(property(get=GetType,put=PutType)) + enum StreamTypeEnum Type; + __declspec(property(get=GetLineSeparator,put=PutLineSeparator)) + enum LineSeparatorEnum LineSeparator; + __declspec(property(get=GetState)) + enum ObjectStateEnum State; + __declspec(property(get=GetMode,put=PutMode)) + enum ConnectModeEnum Mode; + __declspec(property(get=GetCharset,put=PutCharset)) + _bstr_t Charset; + + // + // Wrapper methods for error-handling + // + + long GetSize ( ); + VARIANT_BOOL GetEOS ( ); + long GetPosition ( ); + void PutPosition ( + long pPos ); + enum StreamTypeEnum GetType ( ); + void PutType ( + enum StreamTypeEnum ptype ); + enum LineSeparatorEnum GetLineSeparator ( ); + void PutLineSeparator ( + enum LineSeparatorEnum pLS ); + enum ObjectStateEnum GetState ( ); + enum ConnectModeEnum GetMode ( ); + void PutMode ( + enum ConnectModeEnum pMode ); + _bstr_t GetCharset ( ); + void PutCharset ( + _bstr_t pbstrCharset ); + _variant_t Read ( + long NumBytes ); + HRESULT Open ( + const _variant_t & Source, + enum ConnectModeEnum Mode, + enum StreamOpenOptionsEnum Options, + _bstr_t UserName, + _bstr_t Password ); + HRESULT Close ( ); + HRESULT SkipLine ( ); + HRESULT Write ( + const _variant_t & Buffer ); + HRESULT SetEOS ( ); + HRESULT CopyTo ( + struct _Stream * DestStream, + long CharNumber ); + HRESULT Flush ( ); + HRESULT SaveToFile ( + _bstr_t FileName, + enum SaveOptionsEnum Options ); + HRESULT LoadFromFile ( + _bstr_t FileName ); + _bstr_t ReadText ( + long NumChars ); + HRESULT WriteText ( + _bstr_t Data, + enum StreamWriteEnum Options ); + HRESULT Cancel ( ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_Size ( + long * pSize ) = 0; + virtual HRESULT __stdcall get_EOS ( + VARIANT_BOOL * pEOS ) = 0; + virtual HRESULT __stdcall get_Position ( + long * pPos ) = 0; + virtual HRESULT __stdcall put_Position ( + long pPos ) = 0; + virtual HRESULT __stdcall get_Type ( + enum StreamTypeEnum * ptype ) = 0; + virtual HRESULT __stdcall put_Type ( + enum StreamTypeEnum ptype ) = 0; + virtual HRESULT __stdcall get_LineSeparator ( + enum LineSeparatorEnum * pLS ) = 0; + virtual HRESULT __stdcall put_LineSeparator ( + enum LineSeparatorEnum pLS ) = 0; + virtual HRESULT __stdcall get_State ( + enum ObjectStateEnum * pState ) = 0; + virtual HRESULT __stdcall get_Mode ( + enum ConnectModeEnum * pMode ) = 0; + virtual HRESULT __stdcall put_Mode ( + enum ConnectModeEnum pMode ) = 0; + virtual HRESULT __stdcall get_Charset ( + BSTR * pbstrCharset ) = 0; + virtual HRESULT __stdcall put_Charset ( + BSTR pbstrCharset ) = 0; + virtual HRESULT __stdcall raw_Read ( + long NumBytes, + VARIANT * pval ) = 0; + virtual HRESULT __stdcall raw_Open ( + VARIANT Source, + enum ConnectModeEnum Mode, + enum StreamOpenOptionsEnum Options, + BSTR UserName, + BSTR Password ) = 0; + virtual HRESULT __stdcall raw_Close ( ) = 0; + virtual HRESULT __stdcall raw_SkipLine ( ) = 0; + virtual HRESULT __stdcall raw_Write ( + VARIANT Buffer ) = 0; + virtual HRESULT __stdcall raw_SetEOS ( ) = 0; + virtual HRESULT __stdcall raw_CopyTo ( + struct _Stream * DestStream, + long CharNumber ) = 0; + virtual HRESULT __stdcall raw_Flush ( ) = 0; + virtual HRESULT __stdcall raw_SaveToFile ( + BSTR FileName, + enum SaveOptionsEnum Options ) = 0; + virtual HRESULT __stdcall raw_LoadFromFile ( + BSTR FileName ) = 0; + virtual HRESULT __stdcall raw_ReadText ( + long NumChars, + BSTR * pbstr ) = 0; + virtual HRESULT __stdcall raw_WriteText ( + BSTR Data, + enum StreamWriteEnum Options ) = 0; + virtual HRESULT __stdcall raw_Cancel ( ) = 0; +}; + +struct __declspec(uuid("00000566-0000-0010-8000-00aa006d2ea4")) +Stream; + // [ default ] interface _Stream + +struct __declspec(uuid("00000567-0000-0010-8000-00aa006d2ea4")) +ADORecordConstruction : IDispatch +{ + // + // Property data + // + + __declspec(property(get=GetRow,put=PutRow)) + IUnknownPtr Row; + __declspec(property(put=PutParentRow)) + IUnknownPtr ParentRow; + + // + // Wrapper methods for error-handling + // + + IUnknownPtr GetRow ( ); + void PutRow ( + IUnknown * ppRow ); + void PutParentRow ( + IUnknown * _arg1 ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_Row ( + IUnknown * * ppRow ) = 0; + virtual HRESULT __stdcall put_Row ( + IUnknown * ppRow ) = 0; + virtual HRESULT __stdcall put_ParentRow ( + IUnknown * _arg1 ) = 0; +}; + +struct __declspec(uuid("00000568-0000-0010-8000-00aa006d2ea4")) +ADOStreamConstruction : IDispatch +{ + // + // Property data + // + + __declspec(property(get=GetStream,put=PutStream)) + IUnknownPtr Stream; + + // + // Wrapper methods for error-handling + // + + IUnknownPtr GetStream ( ); + void PutStream ( + IUnknown * ppStm ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_Stream ( + IUnknown * * ppStm ) = 0; + virtual HRESULT __stdcall put_Stream ( + IUnknown * ppStm ) = 0; +}; + +struct __declspec(uuid("00000517-0000-0010-8000-00aa006d2ea4")) +ADOCommandConstruction : IUnknown +{ + // + // Property data + // + + __declspec(property(get=GetOLEDBCommand,put=PutOLEDBCommand)) + IUnknownPtr OLEDBCommand; + + // + // Wrapper methods for error-handling + // + + IUnknownPtr GetOLEDBCommand ( ); + void PutOLEDBCommand ( + IUnknown * ppOLEDBCommand ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_OLEDBCommand ( + IUnknown * * ppOLEDBCommand ) = 0; + virtual HRESULT __stdcall put_OLEDBCommand ( + IUnknown * ppOLEDBCommand ) = 0; +}; + +struct __declspec(uuid("00000507-0000-0010-8000-00aa006d2ea4")) +Command; + // [ default ] interface _Command + +struct __declspec(uuid("00000535-0000-0010-8000-00aa006d2ea4")) +Recordset; + // [ default ] interface _Recordset + // [ default, source ] dispinterface RecordsetEvents + +struct __declspec(uuid("00000283-0000-0010-8000-00aa006d2ea4")) +ADORecordsetConstruction : IDispatch +{ + // + // Property data + // + + __declspec(property(get=GetRowset,put=PutRowset)) + IUnknownPtr Rowset; + __declspec(property(get=GetChapter,put=PutChapter)) + long Chapter; + __declspec(property(get=GetRowPosition,put=PutRowPosition)) + IUnknownPtr RowPosition; + + // + // Wrapper methods for error-handling + // + + IUnknownPtr GetRowset ( ); + void PutRowset ( + IUnknown * ppRowset ); + long GetChapter ( ); + void PutChapter ( + long plChapter ); + IUnknownPtr GetRowPosition ( ); + void PutRowPosition ( + IUnknown * ppRowPos ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_Rowset ( + IUnknown * * ppRowset ) = 0; + virtual HRESULT __stdcall put_Rowset ( + IUnknown * ppRowset ) = 0; + virtual HRESULT __stdcall get_Chapter ( + long * plChapter ) = 0; + virtual HRESULT __stdcall put_Chapter ( + long plChapter ) = 0; + virtual HRESULT __stdcall get_RowPosition ( + IUnknown * * ppRowPos ) = 0; + virtual HRESULT __stdcall put_RowPosition ( + IUnknown * ppRowPos ) = 0; +}; + +struct __declspec(uuid("00000505-0000-0010-8000-00aa006d2ea4")) +Field15 : _ADO +{ + // + // Property data + // + + __declspec(property(get=GetValue,put=PutValue)) + _variant_t Value; + __declspec(property(get=GetName)) + _bstr_t Name; + __declspec(property(get=GetType)) + enum DataTypeEnum Type; + __declspec(property(get=GetDefinedSize)) + long DefinedSize; + __declspec(property(get=GetOriginalValue)) + _variant_t OriginalValue; + __declspec(property(get=GetUnderlyingValue)) + _variant_t UnderlyingValue; + __declspec(property(get=GetActualSize)) + long ActualSize; + __declspec(property(get=GetPrecision)) + unsigned char Precision; + __declspec(property(get=GetNumericScale)) + unsigned char NumericScale; + __declspec(property(get=GetAttributes)) + long Attributes; + + // + // Wrapper methods for error-handling + // + + long GetActualSize ( ); + long GetAttributes ( ); + long GetDefinedSize ( ); + _bstr_t GetName ( ); + enum DataTypeEnum GetType ( ); + _variant_t GetValue ( ); + void PutValue ( + const _variant_t & pvar ); + unsigned char GetPrecision ( ); + unsigned char GetNumericScale ( ); + HRESULT AppendChunk ( + const _variant_t & Data ); + _variant_t GetChunk ( + long Length ); + _variant_t GetOriginalValue ( ); + _variant_t GetUnderlyingValue ( ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_ActualSize ( + long * pl ) = 0; + virtual HRESULT __stdcall get_Attributes ( + long * pl ) = 0; + virtual HRESULT __stdcall get_DefinedSize ( + long * pl ) = 0; + virtual HRESULT __stdcall get_Name ( + BSTR * pbstr ) = 0; + virtual HRESULT __stdcall get_Type ( + enum DataTypeEnum * pDataType ) = 0; + virtual HRESULT __stdcall get_Value ( + VARIANT * pvar ) = 0; + virtual HRESULT __stdcall put_Value ( + VARIANT pvar ) = 0; + virtual HRESULT __stdcall get_Precision ( + unsigned char * pbPrecision ) = 0; + virtual HRESULT __stdcall get_NumericScale ( + unsigned char * pbNumericScale ) = 0; + virtual HRESULT __stdcall raw_AppendChunk ( + VARIANT Data ) = 0; + virtual HRESULT __stdcall raw_GetChunk ( + long Length, + VARIANT * pvar ) = 0; + virtual HRESULT __stdcall get_OriginalValue ( + VARIANT * pvar ) = 0; + virtual HRESULT __stdcall get_UnderlyingValue ( + VARIANT * pvar ) = 0; +}; + +struct __declspec(uuid("0000050b-0000-0010-8000-00aa006d2ea4")) +Parameter; + // [ default ] interface _Parameter + +// +// Wrapper method implementations +// + +#include "msado15.tli" + +} // namespace ADODB + +#pragma pack(pop) diff --git a/st2gpx/src/msado15.tli b/st2gpx/src/msado15.tli new file mode 100644 index 000000000..e72d7a8c0 --- /dev/null +++ b/st2gpx/src/msado15.tli @@ -0,0 +1,2095 @@ +// Created by Microsoft (R) C/C++ Compiler Version 12.00.8168.0 (1f62c7b3). +// +// msado15.tli +// +// Wrapper implementations for Win32 type library msado15.dll +// compiler-generated file created 11/21/03 at 18:38:05 - DO NOT EDIT! + +#pragma once + +// +// interface _Collection wrapper method implementations +// + +inline long _Collection::GetCount ( ) { + long _result; + HRESULT _hr = get_Count(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline IUnknownPtr _Collection::_NewEnum ( ) { + IUnknown * _result; + HRESULT _hr = raw__NewEnum(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return IUnknownPtr(_result, false); +} + +inline HRESULT _Collection::Refresh ( ) { + HRESULT _hr = raw_Refresh(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +// +// interface _DynaCollection wrapper method implementations +// + +inline HRESULT _DynaCollection::Append ( IDispatch * Object ) { + HRESULT _hr = raw_Append(Object); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT _DynaCollection::Delete ( const _variant_t & Index ) { + HRESULT _hr = raw_Delete(Index); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +// +// interface _ADO wrapper method implementations +// + +inline PropertiesPtr _ADO::GetProperties ( ) { + struct Properties * _result; + HRESULT _hr = get_Properties(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return PropertiesPtr(_result, false); +} + +// +// interface Properties wrapper method implementations +// + +inline PropertyPtr Properties::GetItem ( const _variant_t & Index ) { + struct Property * _result; + HRESULT _hr = get_Item(Index, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return PropertyPtr(_result, false); +} + +// +// interface Property wrapper method implementations +// + +inline _variant_t Property::GetValue ( ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = get_Value(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline void Property::PutValue ( const _variant_t & pval ) { + HRESULT _hr = put_Value(pval); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline _bstr_t Property::GetName ( ) { + BSTR _result; + HRESULT _hr = get_Name(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline enum DataTypeEnum Property::GetType ( ) { + enum DataTypeEnum _result; + HRESULT _hr = get_Type(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline long Property::GetAttributes ( ) { + long _result; + HRESULT _hr = get_Attributes(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void Property::PutAttributes ( long plAttributes ) { + HRESULT _hr = put_Attributes(plAttributes); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +// +// interface Error wrapper method implementations +// + +inline long Error::GetNumber ( ) { + long _result; + HRESULT _hr = get_Number(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline _bstr_t Error::GetSource ( ) { + BSTR _result; + HRESULT _hr = get_Source(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline _bstr_t Error::GetDescription ( ) { + BSTR _result; + HRESULT _hr = get_Description(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline _bstr_t Error::GetHelpFile ( ) { + BSTR _result; + HRESULT _hr = get_HelpFile(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline long Error::GetHelpContext ( ) { + long _result; + HRESULT _hr = get_HelpContext(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline _bstr_t Error::GetSQLState ( ) { + BSTR _result; + HRESULT _hr = get_SQLState(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline long Error::GetNativeError ( ) { + long _result; + HRESULT _hr = get_NativeError(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +// +// interface Errors wrapper method implementations +// + +inline ErrorPtr Errors::GetItem ( const _variant_t & Index ) { + struct Error * _result; + HRESULT _hr = get_Item(Index, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return ErrorPtr(_result, false); +} + +inline HRESULT Errors::Clear ( ) { + HRESULT _hr = raw_Clear(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +// +// interface Command15 wrapper method implementations +// + +inline _ConnectionPtr Command15::GetActiveConnection ( ) { + struct _Connection * _result; + HRESULT _hr = get_ActiveConnection(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _ConnectionPtr(_result, false); +} + +inline void Command15::PutRefActiveConnection ( struct _Connection * ppvObject ) { + HRESULT _hr = putref_ActiveConnection(ppvObject); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline void Command15::PutActiveConnection ( const _variant_t & ppvObject ) { + HRESULT _hr = put_ActiveConnection(ppvObject); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline _bstr_t Command15::GetCommandText ( ) { + BSTR _result; + HRESULT _hr = get_CommandText(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline void Command15::PutCommandText ( _bstr_t pbstr ) { + HRESULT _hr = put_CommandText(pbstr); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline long Command15::GetCommandTimeout ( ) { + long _result; + HRESULT _hr = get_CommandTimeout(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void Command15::PutCommandTimeout ( long pl ) { + HRESULT _hr = put_CommandTimeout(pl); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline VARIANT_BOOL Command15::GetPrepared ( ) { + VARIANT_BOOL _result; + HRESULT _hr = get_Prepared(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void Command15::PutPrepared ( VARIANT_BOOL pfPrepared ) { + HRESULT _hr = put_Prepared(pfPrepared); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline _RecordsetPtr Command15::Execute ( VARIANT * RecordsAffected, VARIANT * Parameters, long Options ) { + struct _Recordset * _result; + HRESULT _hr = raw_Execute(RecordsAffected, Parameters, Options, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _RecordsetPtr(_result, false); +} + +inline _ParameterPtr Command15::CreateParameter ( _bstr_t Name, enum DataTypeEnum Type, enum ParameterDirectionEnum Direction, long Size, const _variant_t & Value ) { + struct _Parameter * _result; + HRESULT _hr = raw_CreateParameter(Name, Type, Direction, Size, Value, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _ParameterPtr(_result, false); +} + +inline ParametersPtr Command15::GetParameters ( ) { + struct Parameters * _result; + HRESULT _hr = get_Parameters(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return ParametersPtr(_result, false); +} + +inline void Command15::PutCommandType ( enum CommandTypeEnum plCmdType ) { + HRESULT _hr = put_CommandType(plCmdType); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline enum CommandTypeEnum Command15::GetCommandType ( ) { + enum CommandTypeEnum _result; + HRESULT _hr = get_CommandType(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline _bstr_t Command15::GetName ( ) { + BSTR _result; + HRESULT _hr = get_Name(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline void Command15::PutName ( _bstr_t pbstrName ) { + HRESULT _hr = put_Name(pbstrName); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +// +// interface Connection15 wrapper method implementations +// + +inline _bstr_t Connection15::GetConnectionString ( ) { + BSTR _result; + HRESULT _hr = get_ConnectionString(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline void Connection15::PutConnectionString ( _bstr_t pbstr ) { + HRESULT _hr = put_ConnectionString(pbstr); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline long Connection15::GetCommandTimeout ( ) { + long _result; + HRESULT _hr = get_CommandTimeout(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void Connection15::PutCommandTimeout ( long plTimeout ) { + HRESULT _hr = put_CommandTimeout(plTimeout); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline long Connection15::GetConnectionTimeout ( ) { + long _result; + HRESULT _hr = get_ConnectionTimeout(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void Connection15::PutConnectionTimeout ( long plTimeout ) { + HRESULT _hr = put_ConnectionTimeout(plTimeout); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline _bstr_t Connection15::GetVersion ( ) { + BSTR _result; + HRESULT _hr = get_Version(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline HRESULT Connection15::Close ( ) { + HRESULT _hr = raw_Close(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline _RecordsetPtr Connection15::Execute ( _bstr_t CommandText, VARIANT * RecordsAffected, long Options ) { + struct _Recordset * _result; + HRESULT _hr = raw_Execute(CommandText, RecordsAffected, Options, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _RecordsetPtr(_result, false); +} + +inline long Connection15::BeginTrans ( ) { + long _result; + HRESULT _hr = raw_BeginTrans(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline HRESULT Connection15::CommitTrans ( ) { + HRESULT _hr = raw_CommitTrans(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT Connection15::RollbackTrans ( ) { + HRESULT _hr = raw_RollbackTrans(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT Connection15::Open ( _bstr_t ConnectionString, _bstr_t UserID, _bstr_t Password, long Options ) { + HRESULT _hr = raw_Open(ConnectionString, UserID, Password, Options); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline ErrorsPtr Connection15::GetErrors ( ) { + struct Errors * _result; + HRESULT _hr = get_Errors(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return ErrorsPtr(_result, false); +} + +inline _bstr_t Connection15::GetDefaultDatabase ( ) { + BSTR _result; + HRESULT _hr = get_DefaultDatabase(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline void Connection15::PutDefaultDatabase ( _bstr_t pbstr ) { + HRESULT _hr = put_DefaultDatabase(pbstr); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline enum IsolationLevelEnum Connection15::GetIsolationLevel ( ) { + enum IsolationLevelEnum _result; + HRESULT _hr = get_IsolationLevel(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void Connection15::PutIsolationLevel ( enum IsolationLevelEnum Level ) { + HRESULT _hr = put_IsolationLevel(Level); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline long Connection15::GetAttributes ( ) { + long _result; + HRESULT _hr = get_Attributes(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void Connection15::PutAttributes ( long plAttr ) { + HRESULT _hr = put_Attributes(plAttr); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline enum CursorLocationEnum Connection15::GetCursorLocation ( ) { + enum CursorLocationEnum _result; + HRESULT _hr = get_CursorLocation(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void Connection15::PutCursorLocation ( enum CursorLocationEnum plCursorLoc ) { + HRESULT _hr = put_CursorLocation(plCursorLoc); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline enum ConnectModeEnum Connection15::GetMode ( ) { + enum ConnectModeEnum _result; + HRESULT _hr = get_Mode(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void Connection15::PutMode ( enum ConnectModeEnum plMode ) { + HRESULT _hr = put_Mode(plMode); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline _bstr_t Connection15::GetProvider ( ) { + BSTR _result; + HRESULT _hr = get_Provider(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline void Connection15::PutProvider ( _bstr_t pbstr ) { + HRESULT _hr = put_Provider(pbstr); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline long Connection15::GetState ( ) { + long _result; + HRESULT _hr = get_State(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline _RecordsetPtr Connection15::OpenSchema ( enum SchemaEnum Schema, const _variant_t & Restrictions, const _variant_t & SchemaID ) { + struct _Recordset * _result; + HRESULT _hr = raw_OpenSchema(Schema, Restrictions, SchemaID, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _RecordsetPtr(_result, false); +} + +// +// interface _Connection wrapper method implementations +// + +inline HRESULT _Connection::Cancel ( ) { + HRESULT _hr = raw_Cancel(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +// +// interface Recordset15 wrapper method implementations +// + +inline enum PositionEnum Recordset15::GetAbsolutePosition ( ) { + enum PositionEnum _result; + HRESULT _hr = get_AbsolutePosition(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void Recordset15::PutAbsolutePosition ( enum PositionEnum pl ) { + HRESULT _hr = put_AbsolutePosition(pl); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline void Recordset15::PutRefActiveConnection ( IDispatch * pvar ) { + HRESULT _hr = putref_ActiveConnection(pvar); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline void Recordset15::PutActiveConnection ( const _variant_t & pvar ) { + HRESULT _hr = put_ActiveConnection(pvar); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline _variant_t Recordset15::GetActiveConnection ( ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = get_ActiveConnection(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline VARIANT_BOOL Recordset15::GetBOF ( ) { + VARIANT_BOOL _result; + HRESULT _hr = get_BOF(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline _variant_t Recordset15::GetBookmark ( ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = get_Bookmark(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline void Recordset15::PutBookmark ( const _variant_t & pvBookmark ) { + HRESULT _hr = put_Bookmark(pvBookmark); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline long Recordset15::GetCacheSize ( ) { + long _result; + HRESULT _hr = get_CacheSize(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void Recordset15::PutCacheSize ( long pl ) { + HRESULT _hr = put_CacheSize(pl); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline enum CursorTypeEnum Recordset15::GetCursorType ( ) { + enum CursorTypeEnum _result; + HRESULT _hr = get_CursorType(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void Recordset15::PutCursorType ( enum CursorTypeEnum plCursorType ) { + HRESULT _hr = put_CursorType(plCursorType); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline VARIANT_BOOL Recordset15::GetadoEOF ( ) { + VARIANT_BOOL _result; + HRESULT _hr = get_adoEOF(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline FieldsPtr Recordset15::GetFields ( ) { + struct Fields * _result; + HRESULT _hr = get_Fields(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return FieldsPtr(_result, false); +} + +inline enum LockTypeEnum Recordset15::GetLockType ( ) { + enum LockTypeEnum _result; + HRESULT _hr = get_LockType(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void Recordset15::PutLockType ( enum LockTypeEnum plLockType ) { + HRESULT _hr = put_LockType(plLockType); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline long Recordset15::GetMaxRecords ( ) { + long _result; + HRESULT _hr = get_MaxRecords(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void Recordset15::PutMaxRecords ( long plMaxRecords ) { + HRESULT _hr = put_MaxRecords(plMaxRecords); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline long Recordset15::GetRecordCount ( ) { + long _result; + HRESULT _hr = get_RecordCount(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void Recordset15::PutRefSource ( IDispatch * pvSource ) { + HRESULT _hr = putref_Source(pvSource); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline void Recordset15::PutSource ( _bstr_t pvSource ) { + HRESULT _hr = put_Source(pvSource); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline _variant_t Recordset15::GetSource ( ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = get_Source(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline HRESULT Recordset15::AddNew ( const _variant_t & FieldList, const _variant_t & Values ) { + HRESULT _hr = raw_AddNew(FieldList, Values); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT Recordset15::CancelUpdate ( ) { + HRESULT _hr = raw_CancelUpdate(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT Recordset15::Close ( ) { + HRESULT _hr = raw_Close(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT Recordset15::Delete ( enum AffectEnum AffectRecords ) { + HRESULT _hr = raw_Delete(AffectRecords); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline _variant_t Recordset15::GetRows ( long Rows, const _variant_t & Start, const _variant_t & Fields ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = raw_GetRows(Rows, Start, Fields, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline HRESULT Recordset15::Move ( long NumRecords, const _variant_t & Start ) { + HRESULT _hr = raw_Move(NumRecords, Start); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT Recordset15::MoveNext ( ) { + HRESULT _hr = raw_MoveNext(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT Recordset15::MovePrevious ( ) { + HRESULT _hr = raw_MovePrevious(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT Recordset15::MoveFirst ( ) { + HRESULT _hr = raw_MoveFirst(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT Recordset15::MoveLast ( ) { + HRESULT _hr = raw_MoveLast(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT Recordset15::Open ( const _variant_t & Source, const _variant_t & ActiveConnection, enum CursorTypeEnum CursorType, enum LockTypeEnum LockType, long Options ) { + HRESULT _hr = raw_Open(Source, ActiveConnection, CursorType, LockType, Options); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT Recordset15::Requery ( long Options ) { + HRESULT _hr = raw_Requery(Options); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT Recordset15::_xResync ( enum AffectEnum AffectRecords ) { + HRESULT _hr = raw__xResync(AffectRecords); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT Recordset15::Update ( const _variant_t & Fields, const _variant_t & Values ) { + HRESULT _hr = raw_Update(Fields, Values); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline enum PositionEnum Recordset15::GetAbsolutePage ( ) { + enum PositionEnum _result; + HRESULT _hr = get_AbsolutePage(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void Recordset15::PutAbsolutePage ( enum PositionEnum pl ) { + HRESULT _hr = put_AbsolutePage(pl); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline enum EditModeEnum Recordset15::GetEditMode ( ) { + enum EditModeEnum _result; + HRESULT _hr = get_EditMode(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline _variant_t Recordset15::GetFilter ( ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = get_Filter(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline void Recordset15::PutFilter ( const _variant_t & Criteria ) { + HRESULT _hr = put_Filter(Criteria); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline long Recordset15::GetPageCount ( ) { + long _result; + HRESULT _hr = get_PageCount(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline long Recordset15::GetPageSize ( ) { + long _result; + HRESULT _hr = get_PageSize(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void Recordset15::PutPageSize ( long pl ) { + HRESULT _hr = put_PageSize(pl); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline _bstr_t Recordset15::GetSort ( ) { + BSTR _result; + HRESULT _hr = get_Sort(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline void Recordset15::PutSort ( _bstr_t Criteria ) { + HRESULT _hr = put_Sort(Criteria); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline long Recordset15::GetStatus ( ) { + long _result; + HRESULT _hr = get_Status(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline long Recordset15::GetState ( ) { + long _result; + HRESULT _hr = get_State(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline _RecordsetPtr Recordset15::_xClone ( ) { + struct _Recordset * _result; + HRESULT _hr = raw__xClone(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _RecordsetPtr(_result, false); +} + +inline HRESULT Recordset15::UpdateBatch ( enum AffectEnum AffectRecords ) { + HRESULT _hr = raw_UpdateBatch(AffectRecords); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT Recordset15::CancelBatch ( enum AffectEnum AffectRecords ) { + HRESULT _hr = raw_CancelBatch(AffectRecords); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline enum CursorLocationEnum Recordset15::GetCursorLocation ( ) { + enum CursorLocationEnum _result; + HRESULT _hr = get_CursorLocation(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void Recordset15::PutCursorLocation ( enum CursorLocationEnum plCursorLoc ) { + HRESULT _hr = put_CursorLocation(plCursorLoc); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline _RecordsetPtr Recordset15::NextRecordset ( VARIANT * RecordsAffected ) { + struct _Recordset * _result; + HRESULT _hr = raw_NextRecordset(RecordsAffected, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _RecordsetPtr(_result, false); +} + +inline VARIANT_BOOL Recordset15::Supports ( enum CursorOptionEnum CursorOptions ) { + VARIANT_BOOL _result; + HRESULT _hr = raw_Supports(CursorOptions, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline _variant_t Recordset15::GetCollect ( const _variant_t & Index ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = get_Collect(Index, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline void Recordset15::PutCollect ( const _variant_t & Index, const _variant_t & pvar ) { + HRESULT _hr = put_Collect(Index, pvar); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline enum MarshalOptionsEnum Recordset15::GetMarshalOptions ( ) { + enum MarshalOptionsEnum _result; + HRESULT _hr = get_MarshalOptions(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void Recordset15::PutMarshalOptions ( enum MarshalOptionsEnum peMarshal ) { + HRESULT _hr = put_MarshalOptions(peMarshal); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline HRESULT Recordset15::Find ( _bstr_t Criteria, long SkipRecords, enum SearchDirectionEnum SearchDirection, const _variant_t & Start ) { + HRESULT _hr = raw_Find(Criteria, SkipRecords, SearchDirection, Start); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +// +// interface Recordset20 wrapper method implementations +// + +inline HRESULT Recordset20::Cancel ( ) { + HRESULT _hr = raw_Cancel(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline IUnknownPtr Recordset20::GetDataSource ( ) { + IUnknown * _result; + HRESULT _hr = get_DataSource(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return IUnknownPtr(_result, false); +} + +inline void Recordset20::PutRefDataSource ( IUnknown * ppunkDataSource ) { + HRESULT _hr = putref_DataSource(ppunkDataSource); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline HRESULT Recordset20::_xSave ( _bstr_t FileName, enum PersistFormatEnum PersistFormat ) { + HRESULT _hr = raw__xSave(FileName, PersistFormat); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline IDispatchPtr Recordset20::GetActiveCommand ( ) { + IDispatch * _result; + HRESULT _hr = get_ActiveCommand(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return IDispatchPtr(_result, false); +} + +inline void Recordset20::PutStayInSync ( VARIANT_BOOL pbStayInSync ) { + HRESULT _hr = put_StayInSync(pbStayInSync); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline VARIANT_BOOL Recordset20::GetStayInSync ( ) { + VARIANT_BOOL _result; + HRESULT _hr = get_StayInSync(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline _bstr_t Recordset20::GetString ( enum StringFormatEnum StringFormat, long NumRows, _bstr_t ColumnDelimeter, _bstr_t RowDelimeter, _bstr_t NullExpr ) { + BSTR _result; + HRESULT _hr = raw_GetString(StringFormat, NumRows, ColumnDelimeter, RowDelimeter, NullExpr, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline _bstr_t Recordset20::GetDataMember ( ) { + BSTR _result; + HRESULT _hr = get_DataMember(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline void Recordset20::PutDataMember ( _bstr_t pbstrDataMember ) { + HRESULT _hr = put_DataMember(pbstrDataMember); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline enum CompareEnum Recordset20::CompareBookmarks ( const _variant_t & Bookmark1, const _variant_t & Bookmark2 ) { + enum CompareEnum _result; + HRESULT _hr = raw_CompareBookmarks(Bookmark1, Bookmark2, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline _RecordsetPtr Recordset20::Clone ( enum LockTypeEnum LockType ) { + struct _Recordset * _result; + HRESULT _hr = raw_Clone(LockType, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _RecordsetPtr(_result, false); +} + +inline HRESULT Recordset20::Resync ( enum AffectEnum AffectRecords, enum ResyncEnum ResyncValues ) { + HRESULT _hr = raw_Resync(AffectRecords, ResyncValues); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +// +// interface Recordset21 wrapper method implementations +// + +inline HRESULT Recordset21::Seek ( const _variant_t & KeyValues, enum SeekEnum SeekOption ) { + HRESULT _hr = raw_Seek(KeyValues, SeekOption); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline void Recordset21::PutIndex ( _bstr_t pbstrIndex ) { + HRESULT _hr = put_Index(pbstrIndex); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline _bstr_t Recordset21::GetIndex ( ) { + BSTR _result; + HRESULT _hr = get_Index(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +// +// interface _Recordset wrapper method implementations +// + +inline HRESULT _Recordset::Save ( const _variant_t & Destination, enum PersistFormatEnum PersistFormat ) { + HRESULT _hr = raw_Save(Destination, PersistFormat); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +// +// interface Fields15 wrapper method implementations +// + +inline FieldPtr Fields15::GetItem ( const _variant_t & Index ) { + struct Field * _result; + HRESULT _hr = get_Item(Index, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return FieldPtr(_result, false); +} + +// +// interface Fields20 wrapper method implementations +// + +inline HRESULT Fields20::_Append ( _bstr_t Name, enum DataTypeEnum Type, long DefinedSize, enum FieldAttributeEnum Attrib ) { + HRESULT _hr = raw__Append(Name, Type, DefinedSize, Attrib); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT Fields20::Delete ( const _variant_t & Index ) { + HRESULT _hr = raw_Delete(Index); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +// +// interface Fields wrapper method implementations +// + +inline HRESULT Fields::Append ( _bstr_t Name, enum DataTypeEnum Type, long DefinedSize, enum FieldAttributeEnum Attrib, const _variant_t & FieldValue ) { + HRESULT _hr = raw_Append(Name, Type, DefinedSize, Attrib, FieldValue); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT Fields::Update ( ) { + HRESULT _hr = raw_Update(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT Fields::Resync ( enum ResyncEnum ResyncValues ) { + HRESULT _hr = raw_Resync(ResyncValues); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT Fields::CancelUpdate ( ) { + HRESULT _hr = raw_CancelUpdate(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +// +// interface Field20 wrapper method implementations +// + +inline long Field20::GetActualSize ( ) { + long _result; + HRESULT _hr = get_ActualSize(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline long Field20::GetAttributes ( ) { + long _result; + HRESULT _hr = get_Attributes(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline long Field20::GetDefinedSize ( ) { + long _result; + HRESULT _hr = get_DefinedSize(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline _bstr_t Field20::GetName ( ) { + BSTR _result; + HRESULT _hr = get_Name(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline enum DataTypeEnum Field20::GetType ( ) { + enum DataTypeEnum _result; + HRESULT _hr = get_Type(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline _variant_t Field20::GetValue ( ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = get_Value(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline void Field20::PutValue ( const _variant_t & pvar ) { + HRESULT _hr = put_Value(pvar); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline unsigned char Field20::GetPrecision ( ) { + unsigned char _result; + HRESULT _hr = get_Precision(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline unsigned char Field20::GetNumericScale ( ) { + unsigned char _result; + HRESULT _hr = get_NumericScale(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline HRESULT Field20::AppendChunk ( const _variant_t & Data ) { + HRESULT _hr = raw_AppendChunk(Data); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline _variant_t Field20::GetChunk ( long Length ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = raw_GetChunk(Length, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline _variant_t Field20::GetOriginalValue ( ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = get_OriginalValue(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline _variant_t Field20::GetUnderlyingValue ( ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = get_UnderlyingValue(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline IUnknownPtr Field20::GetDataFormat ( ) { + IUnknown * _result; + HRESULT _hr = get_DataFormat(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return IUnknownPtr(_result, false); +} + +inline void Field20::PutRefDataFormat ( IUnknown * ppiDF ) { + HRESULT _hr = putref_DataFormat(ppiDF); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline void Field20::PutPrecision ( unsigned char pbPrecision ) { + HRESULT _hr = put_Precision(pbPrecision); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline void Field20::PutNumericScale ( unsigned char pbNumericScale ) { + HRESULT _hr = put_NumericScale(pbNumericScale); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline void Field20::PutType ( enum DataTypeEnum pDataType ) { + HRESULT _hr = put_Type(pDataType); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline void Field20::PutDefinedSize ( long pl ) { + HRESULT _hr = put_DefinedSize(pl); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline void Field20::PutAttributes ( long pl ) { + HRESULT _hr = put_Attributes(pl); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +// +// interface Field wrapper method implementations +// + +inline long Field::GetStatus ( ) { + long _result; + HRESULT _hr = get_Status(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +// +// interface _Parameter wrapper method implementations +// + +inline _bstr_t _Parameter::GetName ( ) { + BSTR _result; + HRESULT _hr = get_Name(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline void _Parameter::PutName ( _bstr_t pbstr ) { + HRESULT _hr = put_Name(pbstr); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline _variant_t _Parameter::GetValue ( ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = get_Value(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline void _Parameter::PutValue ( const _variant_t & pvar ) { + HRESULT _hr = put_Value(pvar); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline enum DataTypeEnum _Parameter::GetType ( ) { + enum DataTypeEnum _result; + HRESULT _hr = get_Type(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void _Parameter::PutType ( enum DataTypeEnum psDataType ) { + HRESULT _hr = put_Type(psDataType); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline void _Parameter::PutDirection ( enum ParameterDirectionEnum plParmDirection ) { + HRESULT _hr = put_Direction(plParmDirection); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline enum ParameterDirectionEnum _Parameter::GetDirection ( ) { + enum ParameterDirectionEnum _result; + HRESULT _hr = get_Direction(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void _Parameter::PutPrecision ( unsigned char pbPrecision ) { + HRESULT _hr = put_Precision(pbPrecision); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline unsigned char _Parameter::GetPrecision ( ) { + unsigned char _result; + HRESULT _hr = get_Precision(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void _Parameter::PutNumericScale ( unsigned char pbScale ) { + HRESULT _hr = put_NumericScale(pbScale); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline unsigned char _Parameter::GetNumericScale ( ) { + unsigned char _result; + HRESULT _hr = get_NumericScale(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void _Parameter::PutSize ( long pl ) { + HRESULT _hr = put_Size(pl); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline long _Parameter::GetSize ( ) { + long _result; + HRESULT _hr = get_Size(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline HRESULT _Parameter::AppendChunk ( const _variant_t & Val ) { + HRESULT _hr = raw_AppendChunk(Val); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline long _Parameter::GetAttributes ( ) { + long _result; + HRESULT _hr = get_Attributes(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void _Parameter::PutAttributes ( long plParmAttribs ) { + HRESULT _hr = put_Attributes(plParmAttribs); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +// +// interface Parameters wrapper method implementations +// + +inline _ParameterPtr Parameters::GetItem ( const _variant_t & Index ) { + struct _Parameter * _result; + HRESULT _hr = get_Item(Index, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _ParameterPtr(_result, false); +} + +// +// interface _Command wrapper method implementations +// + +inline long _Command::GetState ( ) { + long _result; + HRESULT _hr = get_State(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline HRESULT _Command::Cancel ( ) { + HRESULT _hr = raw_Cancel(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +// +// interface ConnectionEventsVt wrapper method implementations +// + +inline HRESULT ConnectionEventsVt::InfoMessage ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) { + HRESULT _hr = raw_InfoMessage(pError, adStatus, pConnection); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT ConnectionEventsVt::BeginTransComplete ( long TransactionLevel, struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) { + HRESULT _hr = raw_BeginTransComplete(TransactionLevel, pError, adStatus, pConnection); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT ConnectionEventsVt::CommitTransComplete ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) { + HRESULT _hr = raw_CommitTransComplete(pError, adStatus, pConnection); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT ConnectionEventsVt::RollbackTransComplete ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) { + HRESULT _hr = raw_RollbackTransComplete(pError, adStatus, pConnection); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT ConnectionEventsVt::WillExecute ( BSTR * Source, enum CursorTypeEnum * CursorType, enum LockTypeEnum * LockType, long * Options, enum EventStatusEnum * adStatus, struct _Command * pCommand, struct _Recordset * pRecordset, struct _Connection * pConnection ) { + HRESULT _hr = raw_WillExecute(Source, CursorType, LockType, Options, adStatus, pCommand, pRecordset, pConnection); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT ConnectionEventsVt::ExecuteComplete ( long RecordsAffected, struct Error * pError, enum EventStatusEnum * adStatus, struct _Command * pCommand, struct _Recordset * pRecordset, struct _Connection * pConnection ) { + HRESULT _hr = raw_ExecuteComplete(RecordsAffected, pError, adStatus, pCommand, pRecordset, pConnection); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT ConnectionEventsVt::WillConnect ( BSTR * ConnectionString, BSTR * UserID, BSTR * Password, long * Options, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) { + HRESULT _hr = raw_WillConnect(ConnectionString, UserID, Password, Options, adStatus, pConnection); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT ConnectionEventsVt::ConnectComplete ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) { + HRESULT _hr = raw_ConnectComplete(pError, adStatus, pConnection); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT ConnectionEventsVt::Disconnect ( enum EventStatusEnum * adStatus, struct _Connection * pConnection ) { + HRESULT _hr = raw_Disconnect(adStatus, pConnection); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +// +// interface RecordsetEventsVt wrapper method implementations +// + +inline HRESULT RecordsetEventsVt::WillChangeField ( long cFields, const _variant_t & Fields, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _hr = raw_WillChangeField(cFields, Fields, adStatus, pRecordset); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT RecordsetEventsVt::FieldChangeComplete ( long cFields, const _variant_t & Fields, struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _hr = raw_FieldChangeComplete(cFields, Fields, pError, adStatus, pRecordset); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT RecordsetEventsVt::WillChangeRecord ( enum EventReasonEnum adReason, long cRecords, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _hr = raw_WillChangeRecord(adReason, cRecords, adStatus, pRecordset); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT RecordsetEventsVt::RecordChangeComplete ( enum EventReasonEnum adReason, long cRecords, struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _hr = raw_RecordChangeComplete(adReason, cRecords, pError, adStatus, pRecordset); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT RecordsetEventsVt::WillChangeRecordset ( enum EventReasonEnum adReason, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _hr = raw_WillChangeRecordset(adReason, adStatus, pRecordset); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT RecordsetEventsVt::RecordsetChangeComplete ( enum EventReasonEnum adReason, struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _hr = raw_RecordsetChangeComplete(adReason, pError, adStatus, pRecordset); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT RecordsetEventsVt::WillMove ( enum EventReasonEnum adReason, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _hr = raw_WillMove(adReason, adStatus, pRecordset); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT RecordsetEventsVt::MoveComplete ( enum EventReasonEnum adReason, struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _hr = raw_MoveComplete(adReason, pError, adStatus, pRecordset); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT RecordsetEventsVt::EndOfRecordset ( VARIANT_BOOL * fMoreData, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _hr = raw_EndOfRecordset(fMoreData, adStatus, pRecordset); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT RecordsetEventsVt::FetchProgress ( long Progress, long MaxProgress, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _hr = raw_FetchProgress(Progress, MaxProgress, adStatus, pRecordset); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT RecordsetEventsVt::FetchComplete ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _hr = raw_FetchComplete(pError, adStatus, pRecordset); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +// +// dispinterface ConnectionEvents wrapper method implementations +// + +inline HRESULT ConnectionEvents::InfoMessage ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) { + HRESULT _result; + _com_dispatch_method(this, 0x0, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x0009\x4003\x0009", pError, adStatus, pConnection); + return _result; +} + +inline HRESULT ConnectionEvents::BeginTransComplete ( long TransactionLevel, struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) { + HRESULT _result; + _com_dispatch_method(this, 0x1, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x0003\x0009\x4003\x0009", TransactionLevel, pError, adStatus, pConnection); + return _result; +} + +inline HRESULT ConnectionEvents::CommitTransComplete ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) { + HRESULT _result; + _com_dispatch_method(this, 0x3, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x0009\x4003\x0009", pError, adStatus, pConnection); + return _result; +} + +inline HRESULT ConnectionEvents::RollbackTransComplete ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) { + HRESULT _result; + _com_dispatch_method(this, 0x2, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x0009\x4003\x0009", pError, adStatus, pConnection); + return _result; +} + +inline HRESULT ConnectionEvents::WillExecute ( BSTR * Source, enum CursorTypeEnum * CursorType, enum LockTypeEnum * LockType, long * Options, enum EventStatusEnum * adStatus, struct _Command * pCommand, struct _Recordset * pRecordset, struct _Connection * pConnection ) { + HRESULT _result; + _com_dispatch_method(this, 0x4, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x4008\x4003\x4003\x4003\x4003\x0009\x0009\x0009", Source, CursorType, LockType, Options, adStatus, pCommand, pRecordset, pConnection); + return _result; +} + +inline HRESULT ConnectionEvents::ExecuteComplete ( long RecordsAffected, struct Error * pError, enum EventStatusEnum * adStatus, struct _Command * pCommand, struct _Recordset * pRecordset, struct _Connection * pConnection ) { + HRESULT _result; + _com_dispatch_method(this, 0x5, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x0003\x0009\x4003\x0009\x0009\x0009", RecordsAffected, pError, adStatus, pCommand, pRecordset, pConnection); + return _result; +} + +inline HRESULT ConnectionEvents::WillConnect ( BSTR * ConnectionString, BSTR * UserID, BSTR * Password, long * Options, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) { + HRESULT _result; + _com_dispatch_method(this, 0x6, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x4008\x4008\x4008\x4003\x4003\x0009", ConnectionString, UserID, Password, Options, adStatus, pConnection); + return _result; +} + +inline HRESULT ConnectionEvents::ConnectComplete ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) { + HRESULT _result; + _com_dispatch_method(this, 0x7, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x0009\x4003\x0009", pError, adStatus, pConnection); + return _result; +} + +inline HRESULT ConnectionEvents::Disconnect ( enum EventStatusEnum * adStatus, struct _Connection * pConnection ) { + HRESULT _result; + _com_dispatch_method(this, 0x8, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x4003\x0009", adStatus, pConnection); + return _result; +} + +// +// dispinterface RecordsetEvents wrapper method implementations +// + +inline HRESULT RecordsetEvents::WillChangeField ( long cFields, const _variant_t & Fields, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _result; + _com_dispatch_method(this, 0x9, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x0003\x000c\x4003\x0009", cFields, &Fields, adStatus, pRecordset); + return _result; +} + +inline HRESULT RecordsetEvents::FieldChangeComplete ( long cFields, const _variant_t & Fields, struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _result; + _com_dispatch_method(this, 0xa, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x0003\x000c\x0009\x4003\x0009", cFields, &Fields, pError, adStatus, pRecordset); + return _result; +} + +inline HRESULT RecordsetEvents::WillChangeRecord ( enum EventReasonEnum adReason, long cRecords, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _result; + _com_dispatch_method(this, 0xb, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x0003\x0003\x4003\x0009", adReason, cRecords, adStatus, pRecordset); + return _result; +} + +inline HRESULT RecordsetEvents::RecordChangeComplete ( enum EventReasonEnum adReason, long cRecords, struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _result; + _com_dispatch_method(this, 0xc, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x0003\x0003\x0009\x4003\x0009", adReason, cRecords, pError, adStatus, pRecordset); + return _result; +} + +inline HRESULT RecordsetEvents::WillChangeRecordset ( enum EventReasonEnum adReason, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _result; + _com_dispatch_method(this, 0xd, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x0003\x4003\x0009", adReason, adStatus, pRecordset); + return _result; +} + +inline HRESULT RecordsetEvents::RecordsetChangeComplete ( enum EventReasonEnum adReason, struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _result; + _com_dispatch_method(this, 0xe, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x0003\x0009\x4003\x0009", adReason, pError, adStatus, pRecordset); + return _result; +} + +inline HRESULT RecordsetEvents::WillMove ( enum EventReasonEnum adReason, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _result; + _com_dispatch_method(this, 0xf, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x0003\x4003\x0009", adReason, adStatus, pRecordset); + return _result; +} + +inline HRESULT RecordsetEvents::MoveComplete ( enum EventReasonEnum adReason, struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _result; + _com_dispatch_method(this, 0x10, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x0003\x0009\x4003\x0009", adReason, pError, adStatus, pRecordset); + return _result; +} + +inline HRESULT RecordsetEvents::EndOfRecordset ( VARIANT_BOOL * fMoreData, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _result; + _com_dispatch_method(this, 0x11, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x400b\x4003\x0009", fMoreData, adStatus, pRecordset); + return _result; +} + +inline HRESULT RecordsetEvents::FetchProgress ( long Progress, long MaxProgress, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _result; + _com_dispatch_method(this, 0x12, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x0003\x0003\x4003\x0009", Progress, MaxProgress, adStatus, pRecordset); + return _result; +} + +inline HRESULT RecordsetEvents::FetchComplete ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) { + HRESULT _result; + _com_dispatch_method(this, 0x13, DISPATCH_METHOD, VT_ERROR, (void*)&_result, + L"\x0009\x4003\x0009", pError, adStatus, pRecordset); + return _result; +} + +// +// interface ADOConnectionConstruction15 wrapper method implementations +// + +inline IUnknownPtr ADOConnectionConstruction15::GetDSO ( ) { + IUnknown * _result; + HRESULT _hr = get_DSO(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return IUnknownPtr(_result, false); +} + +inline IUnknownPtr ADOConnectionConstruction15::GetSession ( ) { + IUnknown * _result; + HRESULT _hr = get_Session(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return IUnknownPtr(_result, false); +} + +inline HRESULT ADOConnectionConstruction15::WrapDSOandSession ( IUnknown * pDSO, IUnknown * pSession ) { + HRESULT _hr = raw_WrapDSOandSession(pDSO, pSession); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +// +// interface _Record wrapper method implementations +// + +inline _variant_t _Record::GetActiveConnection ( ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = get_ActiveConnection(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline void _Record::PutActiveConnection ( _bstr_t pvar ) { + HRESULT _hr = put_ActiveConnection(pvar); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline void _Record::PutRefActiveConnection ( struct _Connection * pvar ) { + HRESULT _hr = putref_ActiveConnection(pvar); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline enum ObjectStateEnum _Record::GetState ( ) { + enum ObjectStateEnum _result; + HRESULT _hr = get_State(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline _variant_t _Record::GetSource ( ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = get_Source(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline void _Record::PutSource ( _bstr_t pvar ) { + HRESULT _hr = put_Source(pvar); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline void _Record::PutRefSource ( IDispatch * pvar ) { + HRESULT _hr = putref_Source(pvar); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline enum ConnectModeEnum _Record::GetMode ( ) { + enum ConnectModeEnum _result; + HRESULT _hr = get_Mode(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void _Record::PutMode ( enum ConnectModeEnum pMode ) { + HRESULT _hr = put_Mode(pMode); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline _bstr_t _Record::GetParentURL ( ) { + BSTR _result; + HRESULT _hr = get_ParentURL(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline _bstr_t _Record::MoveRecord ( _bstr_t Source, _bstr_t Destination, _bstr_t UserName, _bstr_t Password, enum MoveRecordOptionsEnum Options, VARIANT_BOOL Async ) { + BSTR _result; + HRESULT _hr = raw_MoveRecord(Source, Destination, UserName, Password, Options, Async, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline _bstr_t _Record::CopyRecord ( _bstr_t Source, _bstr_t Destination, _bstr_t UserName, _bstr_t Password, enum CopyRecordOptionsEnum Options, VARIANT_BOOL Async ) { + BSTR _result; + HRESULT _hr = raw_CopyRecord(Source, Destination, UserName, Password, Options, Async, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline HRESULT _Record::DeleteRecord ( _bstr_t Source, VARIANT_BOOL Async ) { + HRESULT _hr = raw_DeleteRecord(Source, Async); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT _Record::Open ( const _variant_t & Source, const _variant_t & ActiveConnection, enum ConnectModeEnum Mode, enum RecordCreateOptionsEnum CreateOptions, enum RecordOpenOptionsEnum Options, _bstr_t UserName, _bstr_t Password ) { + HRESULT _hr = raw_Open(Source, ActiveConnection, Mode, CreateOptions, Options, UserName, Password); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT _Record::Close ( ) { + HRESULT _hr = raw_Close(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline FieldsPtr _Record::GetFields ( ) { + struct Fields * _result; + HRESULT _hr = get_Fields(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return FieldsPtr(_result, false); +} + +inline enum RecordTypeEnum _Record::GetRecordType ( ) { + enum RecordTypeEnum _result; + HRESULT _hr = get_RecordType(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline _RecordsetPtr _Record::GetChildren ( ) { + struct _Recordset * _result; + HRESULT _hr = raw_GetChildren(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _RecordsetPtr(_result, false); +} + +inline HRESULT _Record::Cancel ( ) { + HRESULT _hr = raw_Cancel(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +// +// interface IRecFields wrapper method implementations +// + +inline HRESULT IRecFields::ADOCheck ( ) { + HRESULT _hr = raw_ADOCheck(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +// +// interface _Stream wrapper method implementations +// + +inline long _Stream::GetSize ( ) { + long _result; + HRESULT _hr = get_Size(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline VARIANT_BOOL _Stream::GetEOS ( ) { + VARIANT_BOOL _result; + HRESULT _hr = get_EOS(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline long _Stream::GetPosition ( ) { + long _result; + HRESULT _hr = get_Position(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void _Stream::PutPosition ( long pPos ) { + HRESULT _hr = put_Position(pPos); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline enum StreamTypeEnum _Stream::GetType ( ) { + enum StreamTypeEnum _result; + HRESULT _hr = get_Type(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void _Stream::PutType ( enum StreamTypeEnum ptype ) { + HRESULT _hr = put_Type(ptype); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline enum LineSeparatorEnum _Stream::GetLineSeparator ( ) { + enum LineSeparatorEnum _result; + HRESULT _hr = get_LineSeparator(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void _Stream::PutLineSeparator ( enum LineSeparatorEnum pLS ) { + HRESULT _hr = put_LineSeparator(pLS); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline enum ObjectStateEnum _Stream::GetState ( ) { + enum ObjectStateEnum _result; + HRESULT _hr = get_State(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline enum ConnectModeEnum _Stream::GetMode ( ) { + enum ConnectModeEnum _result; + HRESULT _hr = get_Mode(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void _Stream::PutMode ( enum ConnectModeEnum pMode ) { + HRESULT _hr = put_Mode(pMode); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline _bstr_t _Stream::GetCharset ( ) { + BSTR _result; + HRESULT _hr = get_Charset(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline void _Stream::PutCharset ( _bstr_t pbstrCharset ) { + HRESULT _hr = put_Charset(pbstrCharset); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline _variant_t _Stream::Read ( long NumBytes ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = raw_Read(NumBytes, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline HRESULT _Stream::Open ( const _variant_t & Source, enum ConnectModeEnum Mode, enum StreamOpenOptionsEnum Options, _bstr_t UserName, _bstr_t Password ) { + HRESULT _hr = raw_Open(Source, Mode, Options, UserName, Password); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT _Stream::Close ( ) { + HRESULT _hr = raw_Close(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT _Stream::SkipLine ( ) { + HRESULT _hr = raw_SkipLine(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT _Stream::Write ( const _variant_t & Buffer ) { + HRESULT _hr = raw_Write(Buffer); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT _Stream::SetEOS ( ) { + HRESULT _hr = raw_SetEOS(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT _Stream::CopyTo ( struct _Stream * DestStream, long CharNumber ) { + HRESULT _hr = raw_CopyTo(DestStream, CharNumber); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT _Stream::Flush ( ) { + HRESULT _hr = raw_Flush(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT _Stream::SaveToFile ( _bstr_t FileName, enum SaveOptionsEnum Options ) { + HRESULT _hr = raw_SaveToFile(FileName, Options); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT _Stream::LoadFromFile ( _bstr_t FileName ) { + HRESULT _hr = raw_LoadFromFile(FileName); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline _bstr_t _Stream::ReadText ( long NumChars ) { + BSTR _result; + HRESULT _hr = raw_ReadText(NumChars, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline HRESULT _Stream::WriteText ( _bstr_t Data, enum StreamWriteEnum Options ) { + HRESULT _hr = raw_WriteText(Data, Options); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT _Stream::Cancel ( ) { + HRESULT _hr = raw_Cancel(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +// +// interface ADORecordConstruction wrapper method implementations +// + +inline IUnknownPtr ADORecordConstruction::GetRow ( ) { + IUnknown * _result; + HRESULT _hr = get_Row(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return IUnknownPtr(_result, false); +} + +inline void ADORecordConstruction::PutRow ( IUnknown * ppRow ) { + HRESULT _hr = put_Row(ppRow); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline void ADORecordConstruction::PutParentRow ( IUnknown * _arg1 ) { + HRESULT _hr = put_ParentRow(_arg1); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +// +// interface ADOStreamConstruction wrapper method implementations +// + +inline IUnknownPtr ADOStreamConstruction::GetStream ( ) { + IUnknown * _result; + HRESULT _hr = get_Stream(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return IUnknownPtr(_result, false); +} + +inline void ADOStreamConstruction::PutStream ( IUnknown * ppStm ) { + HRESULT _hr = put_Stream(ppStm); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +// +// interface ADOCommandConstruction wrapper method implementations +// + +inline IUnknownPtr ADOCommandConstruction::GetOLEDBCommand ( ) { + IUnknown * _result; + HRESULT _hr = get_OLEDBCommand(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return IUnknownPtr(_result, false); +} + +inline void ADOCommandConstruction::PutOLEDBCommand ( IUnknown * ppOLEDBCommand ) { + HRESULT _hr = put_OLEDBCommand(ppOLEDBCommand); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +// +// interface ADORecordsetConstruction wrapper method implementations +// + +inline IUnknownPtr ADORecordsetConstruction::GetRowset ( ) { + IUnknown * _result; + HRESULT _hr = get_Rowset(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return IUnknownPtr(_result, false); +} + +inline void ADORecordsetConstruction::PutRowset ( IUnknown * ppRowset ) { + HRESULT _hr = put_Rowset(ppRowset); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline long ADORecordsetConstruction::GetChapter ( ) { + long _result; + HRESULT _hr = get_Chapter(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void ADORecordsetConstruction::PutChapter ( long plChapter ) { + HRESULT _hr = put_Chapter(plChapter); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline IUnknownPtr ADORecordsetConstruction::GetRowPosition ( ) { + IUnknown * _result; + HRESULT _hr = get_RowPosition(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return IUnknownPtr(_result, false); +} + +inline void ADORecordsetConstruction::PutRowPosition ( IUnknown * ppRowPos ) { + HRESULT _hr = put_RowPosition(ppRowPos); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +// +// interface Field15 wrapper method implementations +// + +inline long Field15::GetActualSize ( ) { + long _result; + HRESULT _hr = get_ActualSize(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline long Field15::GetAttributes ( ) { + long _result; + HRESULT _hr = get_Attributes(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline long Field15::GetDefinedSize ( ) { + long _result; + HRESULT _hr = get_DefinedSize(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline _bstr_t Field15::GetName ( ) { + BSTR _result; + HRESULT _hr = get_Name(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline enum DataTypeEnum Field15::GetType ( ) { + enum DataTypeEnum _result; + HRESULT _hr = get_Type(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline _variant_t Field15::GetValue ( ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = get_Value(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline void Field15::PutValue ( const _variant_t & pvar ) { + HRESULT _hr = put_Value(pvar); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline unsigned char Field15::GetPrecision ( ) { + unsigned char _result; + HRESULT _hr = get_Precision(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline unsigned char Field15::GetNumericScale ( ) { + unsigned char _result; + HRESULT _hr = get_NumericScale(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline HRESULT Field15::AppendChunk ( const _variant_t & Data ) { + HRESULT _hr = raw_AppendChunk(Data); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline _variant_t Field15::GetChunk ( long Length ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = raw_GetChunk(Length, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline _variant_t Field15::GetOriginalValue ( ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = get_OriginalValue(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline _variant_t Field15::GetUnderlyingValue ( ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = get_UnderlyingValue(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} diff --git a/st2gpx/src/nannol.c b/st2gpx/src/nannol.c new file mode 100644 index 000000000..f5f0dd91b --- /dev/null +++ b/st2gpx/src/nannol.c @@ -0,0 +1,206 @@ +/* + nannol.c + + Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format. + + Copyright (C) 2003 James Sherring, james_sherring@yahoo.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + + This app depends on istorage & istorage-make from Pabs (pabs3@zip.to) + and James Clark's Expat xml parser from http://www.libexpat.org/. + +*/ + +#include +#include +#include +#include + +#include "gpx.h" +#include "st2gpx.h" +#include "annotations.h" + +//static int readheight = 0; + +struct annot_rec * gpx2annot_line_rec(struct gpxpt** ptlist, int num_pts, int annot, int version) +{ + int i; + float x; + float y; + float z; + double lat; + double lon; + int count_points_offset; + int line_offset; + + struct annot_rec * rec = annot_rec_new(); + + switch (version) + { + case 3: + count_points_offset = 53; + line_offset = 57; + rec->buf = (char*)xmalloc(line_offset+12*num_pts); + // copy the standard annotation header, + // with appropriate values set + memcpy(rec->buf, std_annot_linerec_header_v3, LINE_REC_LEN_V3); + break; + case 4: + count_points_offset = 53 +4; + line_offset = 57 + 4; + rec->buf = (char*)xmalloc(line_offset+12*num_pts); + // copy the standard annotation header, + // with appropriate values set + memcpy(rec->buf, std_annot_linerec_header_v4, LINE_REC_LEN_V4); + break; + default: + // FIXME version is passed as a param, should be handled there + printf("Unrecognised record format type %d, unable to process more annotations.\n", rec->type); + return NULL; + break; + } + + // set the annotation (record) number + memcpy(rec->buf+4, &annot, 4); + // set the number of points in the line + memcpy(rec->buf+count_points_offset, &num_pts, 4); + + for (i=0; ilat; + lon = ptlist[i]->lon; + // FIXME how do I specify calc in double but return float? + x = (float)(cos(lon*M_PI/180)*cos(lat*M_PI/180)); + y = (float)(sin(lon*M_PI/180)*cos(lat*M_PI/180)); + z = (float)sin(lat*M_PI/180); + + // We can do the height calculations also, + // and s&t will use this in some calculations, including distance, + // but there is no way to visualise or edit height in s&t. + // The example below is for cylindrical height, not radial height. + +/* if (readheight) { + // 6378137 is earths equatorial radius in meters, 20km less at the poles + fac=1+(height/6378137); + x *= fac; + y *= fac; + z *= fac; +*/ + memcpy(rec->buf + line_offset + 12*i, &x, 4); + memcpy(rec->buf + line_offset + 12*i + 4, &y, 4); + memcpy(rec->buf + line_offset + 12*i + 8, &z, 4); + } + + rec->length = line_offset + 12*num_pts; + rec->annot_num = annot; + rec->line_points = num_pts; + rec->line_offset = line_offset; + rec->type = ANNOT_TYPE_LINE; + return rec; +} + +struct annotations * merge_gpx_annot(struct annotations * annots, struct gpx_data* all_gpx) +{ + int i; + int this_annot_num=0; + int tot_num_annots=0; + struct gpxrte * this_rte=NULL; + struct gpxtrk * this_trk=NULL; + + if ( (all_gpx==NULL) || (all_gpx->rte_list_count + all_gpx->trk_list_count==0) ) + return annots; + + if (annots==NULL) + annots = annotations_new(); + + tot_num_annots = annots->num_annotations + all_gpx->rte_list_count + + all_gpx->trk_list_count; + + //printf("reallocing annots, from %d annotations to %d annotations\n", tot_num_annots); + + annots->annot_list = (struct annot_rec**)xrealloc(annots->annot_list, + tot_num_annots*sizeof(struct annot_rec*)); + + // append the gpx routes as annotation lines + for (i=0; i < (all_gpx->rte_list_count); i++) + { + this_annot_num = annots->num_annotations + i; + this_rte = all_gpx->rte_list[i]; + annots->annot_list[this_annot_num] + = gpx2annot_line_rec(this_rte->rtept_list, + this_rte->rtept_list_count, + (annots->max_annot_num)+i+1, + annots->version); + + } + + this_rte=NULL; + annots->num_annotations += all_gpx->rte_list_count; + annots->max_annot_num += all_gpx->rte_list_count; + + // append the gpx tracks as annotation lines + for (i=0; i < all_gpx->trk_list_count; i++) + { + this_annot_num = annots->num_annotations + i; + this_trk = all_gpx->trk_list[i]; + annots->annot_list[this_annot_num] + = gpx2annot_line_rec(this_trk->trkpt_list, + this_trk->trkpt_list_count, + (annots->max_annot_num)+i+1, + annots->version); + } + annots->num_annotations += all_gpx->trk_list_count; + annots->max_annot_num += all_gpx->trk_list_count; + + memcpy(annots->header_buf+8, &(annots->num_annotations), 4); + + return annots; +} + +void write_annotations(struct annotations * annots, char* annot_out_file_name) +{ // Write annotation file header + int status; + int i; + char eostream[4]={0x00, 0x00, 0x00, 0x00}; + FILE* annot_out_file; + + printf("Writing new annotation stream to %s\n", annot_out_file_name); + + if ((annot_out_file = fopen(annot_out_file_name, "wb")) == NULL) { + fprintf(stderr, "Cannot open %s\n", annot_out_file_name); + fflush(stdout); + debug_pause(); + exit(1); + } + + status = fwrite(annots->header_buf, ANNOT_FILE_HEAD_LEN, 1, annot_out_file); + if (status != 1) + printf("expected to write %d, actually wrote %d\n", ANNOT_FILE_HEAD_LEN, status); + + for(i=0; i< annots->num_annotations; i++) + { + status = fwrite(annots->annot_list[i]->buf, annots->annot_list[i]->length, 1, annot_out_file); + if (status != 1) + printf("expected to write %d, actually wrote %d\n", annots->annot_list[i]->length, status); + } + + status = fwrite(eostream, 4, 1, annot_out_file); + if (status != 1) + printf("expected to write %d, actually wrote %d\n", 4, status); + + fclose(annot_out_file); +} diff --git a/st2gpx/src/ppinutil.c b/st2gpx/src/ppinutil.c new file mode 100644 index 000000000..df17bb6f4 --- /dev/null +++ b/st2gpx/src/ppinutil.c @@ -0,0 +1,290 @@ +/* + ppinutil.c + + Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format. + + Copyright (C) 2003 James Sherring, james_sherring@yahoo.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + + This app depends on istorage & istorage-make from Pabs (pabs3@zip.to) + and James Clark's Expat xml parser from http://www.libexpat.org/. + +*/ +#include +#include +#include +#include +#include +#include + +#include "gpx.h" +#include "st2gpx.h" +#include "pushpins.h" + +#include "ppinutil.h" + +struct pushpin_safelist * pushpin_safelist_new() +{ + int i; + struct pushpin_safelist * nw = (struct pushpin_safelist*)xmalloc(sizeof(struct pushpin_safelist)); + nw->pushpin_list=NULL; + nw->num_pushpins=0; + for(i=0; i<3; i++) + { + nw->UDM_Data_length[i]=0; + nw->UDM_Data[i]=NULL; + } + return nw; +} + +void pushpin_safelist_delete(struct pushpin_safelist * ppl) +{ + int i; + if (ppl==NULL) + return; + + for (i=0; inum_pushpins; i++) + pushpin_delete(ppl->pushpin_list[i]); + + xfree(ppl->pushpin_list); + + for(i=0; i<3; i++) + xfree(ppl->UDM_Data[i]); + + xfree(ppl); +} + +struct pushpin * pushpin_new() +{ + struct pushpin * nw = (struct pushpin*)xmalloc(sizeof(struct pushpin)); + nw->garmin_ident[0]=0; + nw->Grid=0; + nw->Precision=0; + nw->lat=0; + nw->lon=0; + nw->NoteShort=NULL; + nw->UdName=NULL; + strcpy(nw->garmin_ident, " "); + return nw; +} + +void pushpin_delete(struct pushpin * pp) +{ + if(pp==NULL) + return; + xfree(pp->NoteShort); + xfree(pp->UdName); + xfree(pp); +} + +struct point grid2latlon(long grid, long precision) +//struct point ms2latlong(struct ms_point msp) +{ +// Convert the 2 long values in UserData stream to GPS coordinates. + +// Grid and Precision are the high and low words obtained by interleaving the bits +// of latitude and longitude. There is a scale factor, so that grid represents +// latitude and longitude value parts more than ~ 1/182.0444 = 360/2^16, +// and precision represents the rest of the values. + +// So we pull each 2n-th bit out, and shift it n places back to the nth longitudinal bit +// and we pull each 2n-th+1 bit out, and shift it n+1 places to the nth latitudinal bit, + + unsigned long int lat_mask=1; + unsigned long int lon_mask=2; + unsigned long int lat_val = 0; + unsigned long int lon_val = 0; + struct point p; + + int i; + + if (grid==0x3FFFFFFF) + { + printf("Got bad Grid value 0x3FFFFFFF converting pushpin data.\n"); + p.lat=-180; + p.lon=-180; + return p; + } + for(i=0; i<16; i++) + { + lat_val += (lat_mask & grid) >> i; + lon_val += (lon_mask & grid) >> (i+1); + lat_mask <<= 2; + lon_mask <<= 2; + } + + + p.lat = (double) lat_val ;// magic1; + p.lon = (double) lon_val ;// magic1; + + lat_mask=1; + lon_mask=2; + lat_val=0; + lon_val=0; + + for (i=0; i<16; i++) + { + lat_val += (lat_mask & precision) >> i; + lon_val += (lon_mask & precision) >> (i+1); + lat_mask <<= 2; + lon_mask <<= 2; + } + +// p.lat += (double) lat_val / (magic2); +// p.lon += (double) lon_val / (magic2); + p.lat += (double) lat_val / (double) (0x10000); + p.lon += (double) lon_val / (double) (0x10000); + + p.lat *= 360/(double) (0x10000); + p.lon *= 360/(double) (0x10000); + + if (p.lon > 180) p.lon -= 360; + if (p.lat > 180) p.lat -= 360; + + if ( (p.lat > 90) || (p.lat < -90) ) + { + printf("Got bad lat value %f converting pushpin data, setting.\n"); +// p.lat=-180; +// p.lon=-180; + } + + return p; +} + +struct grid_point latlon2grid(double lat, double lon) { + + struct grid_point msp; + unsigned long mask=1; + int i; + double scaled_lat = (lat/360) * (0x10000); + double scaled_lon = (lon/360) * (0x10000); + unsigned long lat_grid_ndx = (unsigned long)floor(scaled_lat); + unsigned long lon_grid_ndx = (unsigned long)floor(scaled_lon); + unsigned long lat_prec_ndx = (unsigned long)floor((scaled_lat - lat_grid_ndx)*(0x10000)); + unsigned long lon_prec_ndx = (unsigned long)floor((scaled_lon - lon_grid_ndx)*(0x10000)); + msp.grid=0; + msp.precision=0; + + for(i=0; i<16; i++) { + msp.grid += ((mask & lat_grid_ndx) << i);; + msp.grid += ((mask & lon_grid_ndx) << (i+1)); + mask <<= 1; + } + + mask=1; + for(i=0; i<16; i++) { + msp.precision += ((mask & lat_prec_ndx) << i); + msp.precision += ((mask & lon_prec_ndx) << (i+1)); + mask <<= 1; + } + return msp; +} + +struct pushpin * ppin_by_UdId(int UdId, struct pushpin_safelist * ppplist) +{ + int i; + + //printf("looking to match UdId %d to a pushpin\n", UdId); + //fflush(stdout); + + if (UdId == 0) + return NULL; + + if (ppplist==NULL) + { + printf("Looking for UdId %#x=%d in an empty pushpin list???\n", UdId, UdId); + return NULL; + } + + for (i=0; i< ppplist->num_pushpins; i++) + { + //printf("Comparing to pushpin %d\n", i); + //fflush(stdout); + if(ppplist->pushpin_list[i] == NULL) + return NULL; + + //printf(" with UdId %ld ", (ppplist->pushpin_list[i])->UdId); + //fflush(stdout); + //printf(" and name %s\n", (ppplist->pushpin_list[i])->UdName); + + if ((ppplist->pushpin_list[i]->UdId) == 0) + return NULL; + + if (ppplist->pushpin_list[i]->UdId == UdId) + return ppplist->pushpin_list[i]; + } + return NULL; +} + +int check_file_empty(char* filename) +// FIXME there must be a better way to do this +{ + int readchar; + int retval=0; + FILE* file = fopen(filename, "rb"); + // also check if the file exists + if (file==NULL) + retval= 1; + else + { + readchar = fgetc(file); + if (readchar == EOF) + retval=1; + else + retval=0; + } + if (file) + fclose(file); + return retval; +} + +struct pushpin_safelist * process_pushpin_file(char* ppin_in_file_name) +{ + int i=0; + struct point p; +// struct ms_point msp; + struct pushpin_safelist * ppplist; + + // dont try and open a empty mdb file + if (check_file_empty(ppin_in_file_name)) + return NULL;; + ppplist=read_pushpins(ppin_in_file_name); + + // set lat & lon for all pushpins + while(ppplist->pushpin_list[i] && (inum_pushpins)) + { +// msp.grid = ppplist->pushpin_list[i]->Grid; +// msp.precision = ppplist->pushpin_list[i]->Precision; +// p = grid2latlon(msp); + p = grid2latlon(ppplist->pushpin_list[i]->Grid, ppplist->pushpin_list[i]->Precision); + + ppplist->pushpin_list[i]->lat = p.lat; + ppplist->pushpin_list[i]->lon = p.lon; + + if (opts.verbose_flag > 3) + printf("Decoded pushpin %d lat %f, lon %f, UdName %s, NoteShort %s\n", + ppplist->pushpin_list[i]->UdId, ppplist->pushpin_list[i]->lat, ppplist->pushpin_list[i]->lon, + ppplist->pushpin_list[i]->UdName, ppplist->pushpin_list[i]->NoteShort); + + i++; + } + + printf("Finished reading pushpins\n"); + fflush(stdout); + + return ppplist; +} diff --git a/st2gpx/src/ppinutil.h b/st2gpx/src/ppinutil.h new file mode 100644 index 000000000..cade80e3c --- /dev/null +++ b/st2gpx/src/ppinutil.h @@ -0,0 +1,128 @@ +/* + ppinutil.h + + Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format. + + Copyright (C) 2003 James Sherring, james_sherring@yahoo.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + + This app depends on istorage & istorage-make from Pabs (pabs3@zip.to) + and James Clark's Expat xml parser from http://www.libexpat.org/. + +*/ +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct pushpin_safelist +{ + struct pushpin ** pushpin_list; + int num_pushpins; + char * UDM_Data[3]; + long UDM_Data_length[3]; +} tag_pushpin_safelist; + +typedef struct grid_point { + long grid; + long precision; +} tag_ms_point; + +typedef struct point { + double lon; + double lat; +} tag_point; + +// max size to be read from ppin memo fields +#define MAX_PPIN_MEMO 1000 + +typedef struct pushpin +{ + long UdId; + int SetId; + long Grid; + long Precision; +// dword RenderData; +// byte MatchId; +// long MOBBId; +// long SourceUdId; +// bool IsTerritory; +// + char* UdName; // max 128 +// bool NoNameSearch; +// byte NoteTypeId; + char* NoteShort; // max 255 +// char* NoteLong; // memo +// char* GeocodeShort; // max 255 +// char* GeocodeLong; // memo +// byte GeocodeHierarchy; +// byte GeocodeContext; +// OLE Object EntityArray ???? +// +// shouldn't include these 3 here because they are not part of the native pushpin definition + double lat; + double lon; + // 1 = by hand + // 2 = from file? + // 4 = not matched? + short int MatchId; + long MOBBId; + char garmin_ident[7]; +} tag_pushpin; + + +// not used yet + +typedef struct pushpinset +{ + int SetId; + char* SetName; // max 128 +/* byte RenderMethod; + byte GeocodeMethod; + byte CreateMethod; + byte GeometryType; + char[128] RenderData; + long UdCount; + long MatchedCount; + long SkippedCount; + long UnmatchedCount; + long CounterUpdateMask; + int ParentSetId; + bool IsRendered; + long Z_Order; + long GeocodeCtxt; + OLE Object ThemeRenderData + date/time LastGeocoded + char* DataSrcDescr; // memo + char[30] CurrencyData; +*/ +} tag_pushpinset; + +struct pushpin * pushpin_new(); +void pushpin_delete(struct pushpin * pp); +struct pushpin_safelist * pushpin_safelist_new(); +void pushpin_safelist_delete(struct pushpin_safelist * ppl); + +struct pushpin * ppin_by_UdId(int UdId, struct pushpin_safelist * ppplist); +struct pushpin_safelist * process_pushpin_file(char* ppin_in_file_name); + +//struct point ms2latlong(struct ms_point msp); +struct point grid2latlon(long grid, long precision); +struct grid_point latlon2grid(double lat, double lon); + +#ifdef __cplusplus +} +#endif diff --git a/st2gpx/src/properties.c b/st2gpx/src/properties.c new file mode 100644 index 000000000..b8ef5f070 --- /dev/null +++ b/st2gpx/src/properties.c @@ -0,0 +1,452 @@ +/* + properties.c + + Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format. + + Copyright (C) 2003 James Sherring, james_sherring@yahoo.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + + This app depends on istorage & istorage-make from Pabs (pabs3@zip.to) + and James Clark's Expat xml parser from http://www.libexpat.org/. + +*/ + +// see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnolegen/html/msdn_propset.asp +// http://www.dwam.net/docs/oleref/storage_9.htm + + +#include +#include +#include + +#include "st2gpx.h" +#include "properties.h" + +#define OLE_PROP_STREAM ".Olhud5yvVwudb10uAaq5ezn4Ac" + +// some types from MS, as published at +// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnolegen/html/msdn_propset.asp + +typedef struct PROPERTYSETHEADER +{ + // Header + WORD wByteOrder; // Always 0xFFFE + WORD wFormat; // Always 0 + WORD dwOSVer; // System version + // I needed to add this to get code to work with 1-byte structs alignment; + // It is normally effectively added by VC++ default compiler setting + WORD alignment_fill; + CLSID clsid; // Application CLSID + DWORD dwReserved; // Should be 1 +} PROPERTYSETHEADER; + +typedef struct FORMATIDOFFSET +{ + FMTID fmtid ; // semantic name of a section + DWORD dwOffset ; // offset from start of whole property set + // stream to the section +} FORMATIDOFFSET; + +typedef struct PROPERTYIDOFFSET +{ + DWORD propid; // name of a property + DWORD dwOffset; // offset from the start of the section to that + // property type/value pair +} PROPERTYIDOFFSET; + +typedef struct tagPROPERTYSECTIONHEADER +{ + DWORD cbSection ; // Size of section + DWORD cProperties ; // Count of properties in section + PROPERTYIDOFFSET rgPropIDOffset[]; // Array of property locations +} PROPERTYSECTIONHEADER; + +typedef struct SERIALIZEDPROPERTYVALUE +{ + DWORD dwType; // type tag + BYTE rgb[]; // the actual property value +} SERIALIZEDPROPERTYVALUE; + +/* +typedef struct tagENTRY { + DWORD propid; // Property ID + DWORD cb; // Count of bytes in the string, including the null + // at the end. + char sz[cb]; // Zero-terminated string. Code page as indicated + // by property ID one. + } ENTRY; + +typedef struct tagDICTIONARY { + DWORD cEntries; // Count of entries in the list. + ENTRY rgEntry[cEntries]; + } DICTIONARY; +*/ + +// my defs + +char * fmtid2str(char * str, char * fmtid) +// normal fmtids are a 16B struct, I use a 16B char buf +// fmtid should be 16B long +// str should be 39B long (incl null) +// We need to be careful here to get the byte order correct. +// This seems to match MS's interpretation. +{ + sprintf(str, "{%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x}", + *(unsigned long*)(fmtid), + *(unsigned short*)(fmtid+4), + *(unsigned short*)(fmtid+6), + *(unsigned char*)(fmtid+8), + *(unsigned char*)(fmtid+9), + *(unsigned char*)(fmtid+10), + *(unsigned char*)(fmtid+11), + *(unsigned char*)(fmtid+12), + *(unsigned char*)(fmtid+13), + *(unsigned char*)(fmtid+14), + *(unsigned char*)(fmtid+15) ); + str[39]=0; + return str; +} + +struct ole_property_set * ole_property_set_new(int cProps) +{ + struct ole_property_set * props + =(struct ole_property_set*)xmalloc(sizeof(struct ole_property_set)); + props->cProps = cProps; + props->dict=NULL; + props->pPropList = (struct ole_property*)xmalloc(cProps*sizeof(struct ole_property)); + return props; +} + +void ole_property_set_delete(struct ole_property_set * props) +{ + unsigned int i; + + if ( (props==NULL) || (props->pPropList == NULL) ) + return; + + for(i=0; icProps; i++) + { + xfree(props->pPropList[i].buf); + // FIXME who owns this memory? Cant free it if it is a pointer into another buff + //xfree(props->pPropList[i]); + } + + if (props->dict != NULL) + { + xfree(props->dict->ent_propid); + xfree(props->dict->ent_sz); + xfree(props->dict); + } + xfree(props->pPropList); + xfree(props); +} + + +struct dictionary * read_dictionary(int ents, char* buf, int bufsize) +{ + int ent_read=0; + int bytes_read=0; + int this_ent_cb=0; + struct dictionary * dict = (struct dictionary *)xmalloc(sizeof(struct dictionary)); + dict->cEntries = ents; + dict->ent_propid=(DWORD*)xmalloc(ents*sizeof(DWORD)); + dict->ent_sz=(char**)xmalloc(ents*sizeof(char*)); + + printf("reading %d entries from dictionary\n", ents); + + while(ent_readbufsize) + { + printf("read past end of buffer while reading properties dictionary\n"); + xfree(dict->ent_propid); + xfree(dict->ent_sz); + xfree(dict); + return NULL; + } + + dict->ent_propid[ent_read]=*(DWORD*)(buf+bytes_read); + bytes_read += 4; + + //dict->ent_cb[ent_read]= + this_ent_cb = *(DWORD*)(buf+bytes_read); +// dict->ent_cb[ent_read]=(DWORD*)(buf+bytes_read); + bytes_read += 4; + + if(this_ent_cb > 128) + { + printf("reading dictionary, read entry for propid %#x with name length %d > max allowed length of 128\n", + dict->ent_propid[ent_read], this_ent_cb); +// xfree(dict->ent_cb); + xfree(dict->ent_propid); + xfree(dict->ent_sz); + xfree(dict); + return NULL; + } + + // Dont allocate memory for dictionary strings, + dict->ent_sz[ent_read]=buf+bytes_read; + + // MSDN documentation says cb is bytes, but it is wchars. + bytes_read += 2*this_ent_cb; + + ent_read++; + } + return dict; +} + +unsigned int get_dict_entry(struct dictionary* dict, DWORD propid) +// Find a dictionary entry for a given propid. +// This is then used to get the name for a propid, if available. +{ + unsigned int i; + if (dict==NULL) + return -1; + + for(i=0; icEntries; i++) + if (dict->ent_propid[i] == propid) + return i; + + return 1; +} + +struct ole_property * get_propterty(struct ole_property_set * props, DWORD propid) +{ + unsigned int i; + + if (props==NULL) + return NULL; + + for(i=0; i< props->cProps; i++) + if( props->pPropList[i].propid == propid) + return props->pPropList+i; + + return NULL; +} + +void print_ole_properties(struct ole_property_set * props) +{ + unsigned int i; + unsigned int j; + char* name; + int dict_ent; + char fmtidstr[39]; + char clsidstr[39]; + + if(props==NULL) + return; + + fmtid2str(fmtidstr, props->fmtid); + fmtid2str(clsidstr, props->clsid); + printf("Printing OLE Property Set, with format id %s,\n", fmtidstr); + printf("clsid %s, os %#x osver %#x\n", clsidstr, props->OSKind, props->OSVer); + + for (i=0; i< (props->cProps); i++) + { + name = NULL; + dict_ent = get_dict_entry(props->dict, props->pPropList[i].propid); + if (dict_ent != -1) + name = props->dict->ent_sz[dict_ent]; + + wprintf(L"\nproperty %d: has name %s propid %#x, type %#x, and length %d bytes\n", + i, name, props->pPropList[i].propid, + props->pPropList[i].dwType, props->pPropList[i].buflen ); + + switch(props->pPropList[i].propid) + { + case 0: + printf("This is the property-set dictionary, with entries:\n"); + printf("PropId Property Name\n"); + printf("-----------------------\n"); + for (j=0; jdict->cEntries; j++) + wprintf(L"%#x %s\n", props->dict->ent_propid[j], (props->dict->ent_sz[j])); + break; + case 1: + printf("This specifies codepage %d (1200=Unicode, 1252=Ansi).\n", + *(USHORT*)(props->pPropList[i].buf) ); + break; + case 0x80000000: + printf("This specifies locale %d .\n", + *(unsigned short*)(props->pPropList[i].buf) ); + break; + default: + switch(props->pPropList[i].dwType) + { + case VT_BSTR: //=8 + // the prefix bytecount is still there + wprintf(L"This has value '%ls'\n", props->pPropList[i].buf+4); + break; + case VT_UNKNOWN: //=13 + break; + case VT_BOOL: // =11 + if (*(short*)(props->pPropList[i].buf)) + printf("This has value 'True'\n"); + else + printf("This has value 'False'\n"); + break; + case VT_I4: // = 3 + printf("This has value %d\n", *(int *)(props->pPropList[i].buf) ); + break; + case VT_LPWSTR: //=31 + wprintf(L"This has value '%ls'\n", (props->pPropList[i].buf+4)); + break; + case VT_FILETIME: //=31 + printf("This has value '%s'\n", ctime((const time_t *)props->pPropList[i].buf+4)); + break; + default: + printf("I dont understand this type yet\n"); + printbuf(props->pPropList[i].buf, props->pPropList[i].buflen); + break; + } + } + } +} + +struct ole_property_set * read_ole_properties2(char* prop_file_name) +{ + FILE* prop_file=NULL; + PROPERTYSETHEADER * prop_header = (PROPERTYSETHEADER *)xmalloc(sizeof(PROPERTYSETHEADER)); + FORMATIDOFFSET * fmt_id_os = (FORMATIDOFFSET *)xmalloc(sizeof(FORMATIDOFFSET)); + PROPERTYSECTIONHEADER * psect_header = (PROPERTYSECTIONHEADER *)xmalloc(sizeof(PROPERTYSECTIONHEADER)); + char* section_buff=NULL; + struct ole_property_set * property_set; + + unsigned int i=0; + unsigned int j=0; + unsigned int next_start=0; + int status=0; + + if ((prop_file = fopen(prop_file_name, "rb")) == NULL) + { + fprintf(stderr, "Cannot open property file %s\n", prop_file_name); + return NULL; + } + + status=readbytes(prop_file, (char*)prop_header, sizeof(PROPERTYSETHEADER)); + status=readbytes(prop_file, (char*)fmt_id_os, sizeof(FORMATIDOFFSET)); + + if ( (prop_header->wByteOrder != 0xFFFE) || (prop_header->wFormat != 0) + || (prop_header->dwReserved != 1) || (fmt_id_os->dwOffset !=0x30) ) + { + printf("Not a valid properties set header in file %s\n", prop_file_name); + fclose(prop_file); + return NULL; + } + + status=readbytes(prop_file, (char*)psect_header, sizeof(PROPERTYSECTIONHEADER)); + + psect_header = (PROPERTYSECTIONHEADER *)xrealloc(psect_header, psect_header->cbSection); + section_buff = (char*)psect_header; + + status=readbytes(prop_file, (char*)(psect_header->rgPropIDOffset), + psect_header->cbSection - sizeof(PROPERTYSECTIONHEADER)); + + property_set = ole_property_set_new(psect_header->cProperties); + memcpy(property_set->fmtid, &(fmt_id_os->fmtid), 16); + memcpy(property_set->clsid, &(prop_header->clsid), 16); + property_set->OSKind = *((short int*)( &(prop_header->dwOSVer) ) +1); + property_set->OSVer = *((short int*)( &(prop_header->dwOSVer) )); + + + // We cant rely on pointer order matching data order, + // so we need to do a little extra work to find the start of the next data + for (i=0; i< psect_header->cProperties ; i++) + { + next_start=psect_header->cbSection; //ie end of the buffer + for(j=0; jcProperties; j++) + if( ( psect_header->rgPropIDOffset[i].dwOffset < psect_header->rgPropIDOffset[j].dwOffset ) + && ( psect_header->rgPropIDOffset[j].dwOffset < next_start) ) + next_start = psect_header->rgPropIDOffset[j].dwOffset; + + property_set->pPropList[i].buflen + = next_start + - psect_header->rgPropIDOffset[i].dwOffset + -4; + } + + + for (i=0; i< psect_header->cProperties; i++) + { + property_set->pPropList[i].propid = psect_header->rgPropIDOffset[i].propid; + +// property_set->pPropList[i].buf +// = section_buff + psect_header->rgPropIDOffset[i].dwOffset + 4; + + property_set->pPropList[i].buf = (char*)xmalloc(property_set->pPropList[i].buflen); + memcpy(property_set->pPropList[i].buf, + section_buff + psect_header->rgPropIDOffset[i].dwOffset + 4, + property_set->pPropList[i].buflen); + + property_set->pPropList[i].dwType = *((DWORD*)(section_buff + psect_header->rgPropIDOffset[i].dwOffset)); + } + + for (i=0; i< property_set->cProps; i++) + if (property_set->pPropList[i].propid==0) + property_set->dict=read_dictionary(property_set->pPropList[i].dwType, + property_set->pPropList[i].buf, + property_set->pPropList[i].buflen); + + fclose(prop_file); + xfree(prop_header); + xfree(psect_header); + xfree(fmt_id_os); + + return property_set; +} + +struct ole_property_set * read_ole_properties(char* source_file_name, char* properties_file_name) +{ + char * prop_file_name; + struct ole_property_set * strips_property_set=NULL; + struct ole_property_set * summary_property_set=NULL; + + if ( (source_file_name==NULL) && (properties_file_name==NULL) ) + return NULL; + + if (source_file_name!=NULL) + prop_file_name = (char*)xmalloc(strlen(source_file_name)+40); + else + prop_file_name = properties_file_name; + + strcpy(prop_file_name, source_file_name); + strcpy(prop_file_name + strlen(prop_file_name), ".Contents\\"); + strcpy(prop_file_name + strlen(prop_file_name), OLE_PROP_STREAM); + strips_property_set = read_ole_properties2(prop_file_name); + if (opts.verbose_flag>3) + { + printf("printing properties from %s\n",OLE_PROP_STREAM); + print_ole_properties(strips_property_set); + } + + // We dont really need this next property set, + // but it may be interesting for debuging + if ( (source_file_name != NULL) && (opts.verbose_flag>3) ) + { + strcpy(prop_file_name, source_file_name); + strcpy(prop_file_name + strlen(prop_file_name), ".Contents\\.SummaryInformation"); + summary_property_set = read_ole_properties2(prop_file_name); + printf("printing properties from .SummaryInformation\n"); + print_ole_properties(summary_property_set); + } + + debug_pause(); + + xfree(prop_file_name); + ole_property_set_delete(summary_property_set); + + return strips_property_set; +} diff --git a/st2gpx/src/properties.h b/st2gpx/src/properties.h new file mode 100644 index 000000000..c8d398d58 --- /dev/null +++ b/st2gpx/src/properties.h @@ -0,0 +1,72 @@ +/* + properties.h + + Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format. + + Copyright (C) 2003 James Sherring, james_sherring@yahoo.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + + This app depends on istorage & istorage-make from Pabs (pabs3@zip.to) + and James Clark's Expat xml parser from http://www.libexpat.org/. + +*/ +#ifdef __cplusplus +extern "C" { +#endif + + +typedef unsigned long DWORD; + +typedef struct dictionary +{ + DWORD cEntries; // Count of entries in the list. + // array of propids + DWORD * ent_propid; // Property ID + // This next is an array of pointers into properties value, + // with the string length preceeding (ie X->ent_cb == X->ent_sz -4) + char ** ent_sz; // Zero-terminated string. Code page as indicated. +} tag_dictionary; + +typedef struct ole_property +{ + DWORD propid; + DWORD dwType; // type tag + int buflen; + char* buf; +} tag_ole_property; + +typedef struct ole_property_set +{ +// FMTID fmtid ; // semantic name of a section + char fmtid[16]; // semantic name of a section + char clsid[16]; // clsid for the creating program + int OSKind; // The OS that created the prop-set + int OSVer; + unsigned int cProps; + struct dictionary * dict; + struct ole_property * pPropList; +} tag_ole_property_set; + +struct ole_property_set * read_ole_properties(char* source_file_name, char* properties_file_name); +void ole_property_set_delete(struct ole_property_set * props); +struct ole_property * get_propterty(struct ole_property_set * props, DWORD propid); + + + +#ifdef __cplusplus +} +#endif diff --git a/st2gpx/src/pushpins.cpp b/st2gpx/src/pushpins.cpp index 2143019ee..7bc4f7b30 100644 --- a/st2gpx/src/pushpins.cpp +++ b/st2gpx/src/pushpins.cpp @@ -20,205 +20,570 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA */ -#import "c:\program files\common files\system\ado\msado15.dll" rename ( "EOF", "adoEOF" ) +// FIXME (re)use a single db conection for all recordsets for improved performance + +// for vt type values see http://www.canaimasoft.com/f90VB/OnlineManuals/UserManual/TH_99.htm + +//#import "c:\program files\common files\system\ado\msado15.dll" rename ( "EOF", "adoEOF" ) //#import rename ( "EOF", "adoEOF" ) +#include "msado15.tlh" +#include "msado15.tli" #include #include // Include only once in your application -//#include "adoid.h" // ADO GUID's -//#include "adoint.h" // ADO Classes, enums, etc. #include // for sysstringlength #include -//#include -//#include -//#include #include - +#include "st2gpx.h" +#include "gpx.h" #include "pushpins.h" +#include "ppinutil.h" +#include "contents.h" + struct InitOle { InitOle() { ::CoInitialize(NULL); } ~InitOle() { ::CoUninitialize(); } } _init_InitOle_; -int verbose_flag; -void * xmalloc(size_t size) +VARIANT val2variant(unsigned short fieldtype, void* stor_var) { - void *obj = malloc(size); - if (!obj) - { - fprintf(stderr, "Unable to allocate %d bytes of memory.\n", size); - } - return obj; -} + VARIANT vt_val; + vt_val.vt=fieldtype; -LPWSTR wstr2cpy(BSTR wstr) -{ - int len=wcslen(wstr); - LPWSTR newstr=(LPWSTR)xmalloc((len+1)*sizeof(WCHAR)); - wcscpy(newstr, wstr); - return newstr; -} + // not sure if this is neccessary + VariantInit(&vt_val); -char* wstr2str(BSTR wstr) -// there must be a better way to do this -{ - int len; - int i; - char* newstr=NULL; - // call to get length - len = WideCharToMultiByte( - CP_THREAD_ACP, - 0, - wstr, - -1, - newstr, - 0, - NULL, - 0); - if(len==0) + switch (fieldtype) { - //printf("wide2normal got length %d\n", len); - len=wcslen(wstr); - //printf("wide2normal cheated and got length %d\n", len); - }; - newstr = (char*)xmalloc((len+1)*sizeof(char)); - // now call to set string - len = WideCharToMultiByte( - CP_THREAD_ACP, - 0, - wstr, - -1, - newstr, - len, - NULL, - 0); - //printf("wide2normal copied %d chars and got string %s\n", len, newstr); - if (len==0) - { - len=wcslen(wstr); - for(i=0; ipushpin_list = (struct pushpin **)xmalloc(ppin_list_alloc_size*sizeof(struct pushpin *)); + + if (opts.st_version_num<9) + ppin_sql = "SELECT UD_Secondary.UdId, UD_Secondary.UdName, UD_Secondary.NoteShort, UD_Secondary.NoteLong, UD_Main.Grid, UD_Main.Precision, UD_Main.MatchId, UD_Main.MOBBId FROM UD_Main INNER JOIN UD_Secondary ON UD_Main.UdId = UD_Secondary.UdId"; + else + ppin_sql = "SELECT UdId, UdName, NoteShort, NoteLong, Grid, Precision, MatchId, MOBBId FROM UD_Main"; + try { HRESULT hr = S_OK; ADODB::_RecordsetPtr rs; char cnstr[500]; - char sqlstr[] = "SELECT UD_Secondary.UdId, UD_Secondary.UdName, UD_Secondary.NoteShort, UD_Secondary.NoteLong, UD_Main.Grid, UD_Main.Precision FROM UD_Main INNER JOIN UD_Secondary ON UD_Main.UdId = UD_Secondary.UdId"; sprintf(cnstr, "PROVIDER=Microsoft.Jet.OLEDB.4.0;data source=%s; Jet OLEDB:Database Password=Geo80;", ppin_file_name); hr = rs.CreateInstance( __uuidof( ADODB::Recordset ) ); - hr = rs->Open(sqlstr, + + // ***************** + // Read GEODB_LastId + // ***************** + + // FIXME read dbversion, use that instead of file version for setting sql + + // ************* + // read pushpins + // ************* + + hr = rs->Open(ppin_sql, cnstr, ADODB::adOpenForwardOnly, ADODB::adLockReadOnly, -1 ); - hr = rs->MoveFirst(); + while ((rs->adoEOF == FALSE)) { - ppin = (struct pushpin *)xmalloc(sizeof(struct pushpin)); + ppin = pushpin_new(); + + variant2val(rs->Fields->GetItem("UdId")->Value, VT_I4, &(ppin->UdId)); + variant2val(rs->Fields->GetItem("UdName")->Value, VT_BSTR,&(ppin->UdName)); + variant2val(rs->Fields->GetItem("Grid")->Value, VT_I4, &(ppin->Grid)); + variant2val(rs->Fields->GetItem("Precision")->Value,VT_I4, &(ppin->Precision)); + variant2val(rs->Fields->GetItem("NoteShort")->Value,VT_BSTR,&(ppin->NoteShort)); + variant2val(rs->Fields->GetItem("MatchId")->Value, VT_I2, &(ppin->MatchId)); + variant2val(rs->Fields->GetItem("MOBBId")->Value, VT_I4, &(ppin->MOBBId)); - readfield(rs->Fields->GetItem("UdId")->Value, VT_I4, &(ppin->UdId)); - readfield(rs->Fields->GetItem("UdName")->Value, VT_BSTR,&(ppin->UdName)); - readfield(rs->Fields->GetItem("Grid")->Value, VT_I4, &(ppin->Grid)); - readfield(rs->Fields->GetItem("Precision")->Value, VT_I4, &(ppin->Precision)); - readfield(rs->Fields->GetItem("NoteShort")->Value, VT_BSTR,&(ppin->NoteShort)); + str2ascii(ppin->UdName); + str2ascii(ppin->NoteShort); - if (verbose_flag > 3) + if (opts.verbose_flag > 3) printf("Read pushpin UdId=%d, UdName=%s, Grid=%d, Precision=%d, NoteShort=%s\n", ppin->UdId, ppin->UdName, ppin->Grid, ppin->Precision, ppin->NoteShort); - - ppin_list[ppinnum]=ppin; - ppinnum++; - if (ppinnum>MAX_PUSHPINS-1) + // what are the valid matchIds? + if (ppin->MatchId==4) { - printf("Exceeded maximun number of pushpins (I should fix this)\n"); - break; + printf("Read unmatched pushpin UdId=%d, UdName=%s, Grid=%d, Precision=%d, NoteShort=%s\n", + ppin->UdId, ppin->UdName, + ppin->Grid, ppin->Precision, ppin->NoteShort); + printf("Discarding this pushpin because it is not geocoded (i.e. not matched to map).\n"); + pushpin_delete(ppin); + } + else + { + ppplist->pushpin_list[ppinnum]=ppin; + ppinnum++; + if (ppinnum>ppin_list_alloc_size-1) + { + ppin_list_alloc_size += 100; + ppplist->pushpin_list = (struct pushpin **)xrealloc(ppplist->pushpin_list, ppin_list_alloc_size*sizeof(struct pushpin *)); + } } - hr = rs->MoveNext(); } hr = rs->Close(); - rs = NULL; + + // ************* + // read UDM_Data + // ************* + + if (opts.explore_flag) + { + UDM_sql = "Select UdmDataId, UdmData from UDM_Data"; + + hr = rs->Open(UDM_sql, + cnstr, + ADODB::adOpenForwardOnly, + ADODB::adLockReadOnly, + -1 ); + + while ((rs->adoEOF == FALSE)) + { + variant2val(rs->Fields->GetItem("UdmDataId")->Value, VT_I4, &UdmDataId); + if ( (UdmDataId<0) || (UdmDataId>3) ) + { + printf("*** Unexpected UdmDataId=%d\n", UdmDataId); + break; + } + + ppplist->UDM_Data_length[UdmDataId] = rs->Fields->GetItem("UdmData")->ActualSize; + ppplist->UDM_Data[UdmDataId]=(char*)xmalloc(ppplist->UDM_Data_length[UdmDataId]); + variant2val(rs->Fields->GetItem("UdmData")->Value, VT_ARRAY | VT_UI1, ppplist->UDM_Data[UdmDataId]); + + printf("In UDM_Data table, for UdId=%d got %d bytes of data\n", + UdmDataId, ppplist->UDM_Data_length[UdmDataId]); + printbuf(ppplist->UDM_Data[UdmDataId], ppplist->UDM_Data_length[UdmDataId]); + + hr = rs->MoveNext(); + } + hr = rs->Close(); + } + + rs = NULL; + } catch( _com_error &e) { _bstr_t bstrSource(e.Source()); - _bstr_t bs = _bstr_t(" Error: ") + _bstr_t(e.Error()) + _bstr_t(" Msg: ") + _bstr_t bs = _bstr_t("*** Exception: ") + _bstr_t(e.Error()) + _bstr_t(" Msg: ") + + _bstr_t(e.ErrorMessage()) + _bstr_t(" Description: ") + + _bstr_t(e.Description()); + + wprintf(bs); + _flushall(); + + if (opts.verbose_flag>4) + MessageBox(0,bs,bstrSource, MB_OK); + } + + if (opts.verbose_flag > 1) + printf("Read %d pushpins from %s.\n", ppinnum, ppin_file_name); + + ppplist->num_pushpins=ppinnum; + return ppplist; +} + +EXTERN_C void write_pushpins_from_gpx(char* ppin_file_name, + struct gpx_data * all_gpx, + struct contents * conts, + char* conts_file_name) +{ + short int DbVersion=0; + int LastSetId=0; + long LastUserDataId=0; + long thisfirstUserDataId=0; + long thisUserDataId=0; + char* sql; + char* sql2; + + // nothing to write + if (all_gpx->wpt_list_count==0) + return; + + try + { + HRESULT hr = S_OK; + ADODB::_RecordsetPtr rs; + ADODB::_RecordsetPtr rs2; + char cnstr[500]; + sprintf(cnstr, "PROVIDER=Microsoft.Jet.OLEDB.4.0;data source=%s; Jet OLEDB:Database Password=Geo80;", ppin_file_name); + + hr = rs.CreateInstance( __uuidof( ADODB::Recordset ) ); + + // ***************** + // Read GEODB_LastId + // ***************** + + sql = "select DbVersion, LastSetId, LastUserDataId from GEODB_LastId"; + hr = rs->Open(sql, + cnstr, + ADODB::adOpenKeyset, + ADODB::adLockOptimistic, + -1 ); + + variant2val(rs->Fields->GetItem("DbVersion")->Value, VT_I2, &DbVersion); + variant2val(rs->Fields->GetItem("LastSetId")->Value, VT_I4, &LastSetId); + variant2val(rs->Fields->GetItem("LastUserDataId")->Value, VT_I4, &LastUserDataId); + + printf("Got DbVersion=%d, LastSetId=%d and LastUserDataId=%d\n", DbVersion, LastSetId, LastUserDataId); + + // ***************** + // update LastSetId, LastUserDataId in GEODB_LastId + // ***************** + + // Later we might import pushpins as different sets, + // but for now we just import as one set + + LastSetId += 1; + thisfirstUserDataId = LastUserDataId +1; + LastUserDataId += all_gpx->wpt_list_count; + + rs->Fields->GetItem("LastSetId" )->Value = val2variant(VT_I4, &LastSetId); + rs->Fields->GetItem("LastUserDataId")->Value = val2variant(VT_I4, &LastUserDataId); + + rs->Update(); + hr = rs->Close(); + //printf("Updated LastSetId, LastUserDataId in GEODB_LastId\n"); + + + // ****************** + // Write all pushpins + // ****************** + + if (opts.st_version_num<9) + { + sql = "Select UdId, SetId, Grid, Precision, MatchId, MOBBId, SourceUdId from UD_Main"; + sql2 = "Select UdId, NoteTypeId, GeocodeHierarchy, GeocodeContext, UdName, NoteShort, NoteLong from UD_Secondary"; + hr = rs->Open(sql, + cnstr, + ADODB::adOpenKeyset, + ADODB::adLockOptimistic, + -1 ); + hr = rs2.CreateInstance( __uuidof( ADODB::Recordset ) ); + hr = rs2->Open(sql2, + cnstr, + ADODB::adOpenKeyset, + ADODB::adLockOptimistic, + -1 ); + } + else + { + sql = "Select UdId, SetId, Grid, Precision, MatchId, MOBBId, SourceUdId, NoteTypeId, GeocodeHierarchy, GeocodeContext, UdName, NoteShort, NoteLong from UD_Main"; + // maybe we have to do this later, when rs is set? + hr = rs->Open(sql, + cnstr, + ADODB::adOpenKeyset, + ADODB::adLockOptimistic, + -1 ); + } + + + int w; + struct gpxpt * gpt; + struct grid_point gridpt; + long lzero=0; + short int sizero=0; + short int sione=1; + short int sitwo=2; + + // do for each wpt + for(w=0; wwpt_list_count; w++) + { + if (opts.st_version_num<9) + { + rs->AddNew(); + rs2->AddNew(); + } + else + { + rs->AddNew(); + rs2 = rs; + } + + thisUserDataId=thisfirstUserDataId+w; + gpt = all_gpx->wpt_list[w]; + gridpt=latlon2grid(gpt->lat, gpt->lon); + + //printf("writing ppin with thisUserDataId=%d, gpt->name=%s\n", thisUserDataId, gpt->name); + + rs->Fields->GetItem("UdId" )->Value = val2variant(VT_I4, &thisUserDataId); + rs->Fields->GetItem("SetId" )->Value = val2variant(VT_I2, &LastSetId); + rs->Fields->GetItem("Grid" )->Value = val2variant(VT_I4, &(gridpt.grid)); + rs->Fields->GetItem("Precision" )->Value = val2variant(VT_I4, &(gridpt.precision)); + rs->Fields->GetItem("MatchId" )->Value = val2variant(VT_I2, &sitwo); + rs->Fields->GetItem("MOBBId" )->Value = val2variant(VT_I4, &lzero); + rs->Fields->GetItem("SourceUdId")->Value = val2variant(VT_I4, &lzero); + + if (opts.st_version_num<9) + rs->Update(); + + rs2->Fields->GetItem("UdId" )->Value = val2variant(VT_I4, &thisUserDataId); + rs2->Fields->GetItem("UdName" )->Value = val2variant(VT_BSTR,(gpt->name)); + rs2->Fields->GetItem("NoteTypeId")->Value = val2variant(VT_I2, &sione); + rs2->Fields->GetItem("NoteShort")->Value = val2variant(VT_BSTR,(gpt->desc)); + rs2->Fields->GetItem("GeocodeHierarchy")->Value = val2variant(VT_I2, &sizero); + rs2->Fields->GetItem("GeocodeContext" )->Value = val2variant(VT_I4, &lzero); + // sometime I should support this + // rs2->Fields->GetItem("NoteLong" )->Value = val2variant(?, NULL); + rs2->Update(); + } + + if (opts.st_version_num<9) + { + rs->Close(); + rs2->Close(); + rs2 = NULL; + } + else + { + rs->Close(); + } + + //printf("Inserted all pushpin records\n"); + + // ********************** + // insert row in SET_Main, + // ********************** + + // SetId, SetName, UdCount, MatchedCount + + // FIXME cant I use a compiler var for size of largest short? + if (LastSetId>(1<<15)) + printf("too many set ids!"); + short int SetId=(short int)LastSetId; + + char* SetName = all_gpx->data_source_name; + short int RenderMethod = 2; + short int GeocodeMethod = 5; + short int CreateMethod = 2; + short int GeometryType = 1; + long UdCount=all_gpx->wpt_list_count; + long MatchedCount=all_gpx->wpt_list_count; + long SkippedCount = 0; + long UnmatchedCount = 0; + long CounterUpdateMask=0; + short int ParentSetId=0; + short int IsRendered=-1; + long Z_Order=0; //5000; + long GeocodeCtxt=39070; // ??? + int HLnkSrc=3; + long HLnkColId=0; + + if(opts.st_version_num<9) + sql = "SELECT SetId, SetName, RenderMethod, GeocodeMethod, CreateMethod, GeometryType, UdCount, MatchedCount, SkippedCount, UnmatchedCount, CounterUpdateMask, ParentSetId, IsRendered, Z_Order, GeocodeCtxt FROM SET_Main"; + else + sql = "SELECT SetId, SetName, RenderMethod, GeocodeMethod, CreateMethod, GeometryType, UdCount, MatchedCount, SkippedCount, UnmatchedCount, CounterUpdateMask, ParentSetId, IsRendered, Z_Order, GeocodeCtxt, HLnkSrc, HLnkColId FROM SET_Main"; + + hr = rs->Open(sql, + cnstr, + ADODB::adOpenKeyset, + ADODB::adLockOptimistic, + -1 ); + + rs->AddNew(); + + rs->Fields->GetItem("SetId" )->Value = val2variant(VT_I2, &SetId); + rs->Fields->GetItem("SetName" )->Value = val2variant(VT_BSTR, SetName); + rs->Fields->GetItem("RenderMethod" )->Value = val2variant(VT_I2, &RenderMethod); + rs->Fields->GetItem("GeocodeMethod" )->Value = val2variant(VT_I2, &GeocodeMethod); + rs->Fields->GetItem("CreateMethod" )->Value = val2variant(VT_I2, &CreateMethod); + rs->Fields->GetItem("GeometryType" )->Value = val2variant(VT_I2, &GeometryType); + rs->Fields->GetItem("UdCount" )->Value = val2variant(VT_I4, &UdCount); + rs->Fields->GetItem("MatchedCount" )->Value = val2variant(VT_I4, &MatchedCount); + rs->Fields->GetItem("SkippedCount" )->Value = val2variant(VT_I4, &SkippedCount); + rs->Fields->GetItem("UnmatchedCount" )->Value = val2variant(VT_I4, &UnmatchedCount); + rs->Fields->GetItem("CounterUpdateMask" )->Value = val2variant(VT_I4, &CounterUpdateMask); + rs->Fields->GetItem("ParentSetId" )->Value = val2variant(VT_I2, &ParentSetId); + rs->Fields->GetItem("IsRendered" )->Value = val2variant(VT_I2, &IsRendered); + rs->Fields->GetItem("Z_Order" )->Value = val2variant(VT_I4, &Z_Order); + rs->Fields->GetItem("GeocodeCtxt" )->Value = val2variant(VT_I4, &GeocodeCtxt); + + if(opts.st_version_num>8) + { + rs->Fields->GetItem("HLnkSrc" )->Value = val2variant(VT_I2, &HLnkSrc); + rs->Fields->GetItem("HLnkColId" )->Value = val2variant(VT_I4, &HLnkColId); + } + + rs->Update(); + rs->Close(); + + + // *************************** + // construct & update UDM_data + // *************************** + + // we need to do this to show ppin name, info, symbol etc + + // ******************* + // COM / ADO clean up + // ******************* + + rs = NULL; + if (rs2) + rs2 = NULL; + + // ***************** + // update contents + // ***************** + + struct contents * mod_conts = contents_insert_ppinset(conts, (unsigned short)LastSetId); + if (mod_conts!=NULL) + { + write_contents(mod_conts, conts_file_name); + contents_delete(mod_conts); + + printf("Wrote %d waypoints as PushPins\n", all_gpx->wpt_list_count); + debug_pause(); + } + else + printf("failed to successfully write pushpins, output is now corrupt.\n"); + } + catch( _com_error &e) + { + _bstr_t bstrSource(e.Source()); + _bstr_t bs = _bstr_t("*** Exception: ") + _bstr_t(e.Error()) + _bstr_t(" Msg: ") + _bstr_t(e.ErrorMessage()) + _bstr_t(" Description: ") + _bstr_t(e.Description()); + + wprintf(bs); + _flushall(); - MessageBox(0,bs,bstrSource, MB_OK); +// if (opts.verbose_flag>4) + MessageBox(0,bs,bstrSource, MB_OK); } + } diff --git a/st2gpx/src/pushpins.h b/st2gpx/src/pushpins.h index e699a409f..425391cec 100644 --- a/st2gpx/src/pushpins.h +++ b/st2gpx/src/pushpins.h @@ -25,72 +25,13 @@ extern "C" { #endif -#define MAX_PUSHPINS 5000 - -// max size to be read from ppin memo fields -#define MAX_PPIN_MEMO 1000 - -typedef struct pushpin -{ - long UdId; - int SetId; - long Grid; - long Precision; -// dword RenderData; -// byte MatchId; -// long MOBBId; -// long SourceUdId; -// bool IsTerritory; -// - char* UdName; // max 128 -// bool NoNameSearch; -// byte NoteTypeId; - char* NoteShort; // max 255 -// char* NoteLong; // memo -// char* GeocodeShort; // max 255 -// char* GeocodeLong; // memo -// byte GeocodeHierarchy; -// byte GeocodeContext; -// OLE Object EntityArray ???? -// -// shouldn't include these two here because they are not part of the native pushpin definition - double lat; - double lon; -} tag_pushpin; - - -typedef struct pushpinset -{ - int SetId; - char* SetName; // max 128 -/* byte RenderMethod; - byte GeocodeMethod; - byte CreateMethod; - byte GeometryType; - char[128] RenderData; - long UdCount; - long MatchedCount; - long SkippedCount; - long UnmatchedCount; - long CounterUpdateMask; - int ParentSetId; - bool IsRendered; - long Z_Order; - long GeocodeCtxt; - OLE Object ThemeRenderData - date/time LastGeocoded - char* DataSrcDescr; // memo - char[30] CurrencyData; -*/ -} tag_pushpinset; - -//struct pushpin * ppin_list[MAX_PUSHPINS]; -struct pushpin * ppin_list[5000]; - -//EXTERN_C - void read_ppin_list(char* ppin_file_name); - - +//EXTERN_C +struct pushpin_safelist * read_pushpins(char* ppin_file_name); +//EXTERN_C +void write_pushpins_from_gpx(char* ppin_file_name, + struct gpx_data * all_gpx, + struct contents * conts, + char* conts_file_name); #ifdef __cplusplus } /* closing brace for extern "C" */ #endif diff --git a/st2gpx/src/readgpx.c b/st2gpx/src/readgpx.c new file mode 100644 index 000000000..e9da430d3 --- /dev/null +++ b/st2gpx/src/readgpx.c @@ -0,0 +1,656 @@ +/* + readgpx.c + + Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format. + + Copyright (C) 2003 James Sherring, james_sherring@yahoo.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + + This app depends on istorage & istorage-make from Pabs (pabs3@zip.to) + and James Clark's Expat xml parser from http://www.libexpat.org/. + +*/ + +#include +#include +#include + +#include +#include "gpx.h" +#include "st2gpx.h" + + +typedef void (*gpx_elm_start_handler)(void *, const char *, const char **); +typedef void (*gpx_elm_end_handler)(void *, const char *); + +int current_main_element=0; +int current_element=0; +static XML_Char * cdata; +static int cdata_length; + +//FILE* gpx_in_file=NULL; + +char * gpx_elem_name[] = +{ + "unknown-element", + "wpt", + "rte", + "rtept", + "trk", + "trkseg", + "trkpt", + "name", + "desc", + "src" +}; + +struct gpxpt * gpxpt_new() +{ + struct gpxpt * nw = (struct gpxpt *)xmalloc(sizeof(struct gpxpt)); + nw->name=NULL; + nw->desc=NULL; + nw->lat=0; + nw->lon=0; + nw->elevation=0; + nw->use_elevation=0; + return nw; +} + +void gpxpt_delete(struct gpxpt * pt) +{ + if(pt==NULL) + return; + xfree(pt->name); + xfree(pt->desc); + xfree(pt); +} + +struct gpxpt * gpxpt_copy(struct gpxpt * otherpt) +{ + struct gpxpt * nw = (struct gpxpt *)xmalloc(sizeof(struct gpxpt)); + nw->name=xmalloc(strlen(otherpt->name)+1); + strcpy(nw->name, otherpt->name); + nw->desc=xmalloc(strlen(otherpt->desc)+1); + strcpy(nw->desc, otherpt->desc); + nw->lat=otherpt->lat; + nw->lon=otherpt->lon; + nw->elevation=otherpt->elevation; + nw->use_elevation=otherpt->use_elevation; + return nw; +} + +struct gpxpt * find_matching_wpt(struct gpx_data * dat, char* name) +{ + int i; + struct gpxpt * match = NULL; + for(i=0; iwpt_list_count; i++) + if(strcmp(name, dat->wpt_list[i]->name)==0) + { + match = dat->wpt_list[i]; + break; + } + return match; +} + +struct gpxrte * gpxrte_new() +{ + struct gpxrte * nw = (struct gpxrte *)xmalloc(sizeof(struct gpxrte)); + nw->name=NULL; + nw->rtept_list=NULL; + nw->rtept_list_count=0; + return nw; +} + +void gpxrte_delete(struct gpxrte * rte) +{ + int i; + if(rte==NULL) + return; + for (i=0; irtept_list_count; i++) + gpxpt_delete(rte->rtept_list[i]); + xfree(rte->rtept_list); + xfree(rte->name); + xfree(rte); +} + +struct gpxtrk * gpxtrk_new() +{ + struct gpxtrk * nw = (struct gpxtrk *)xmalloc(sizeof(struct gpxtrk)); + nw->trkpt_list=NULL; + nw->trkpt_list_count=0; + return nw; +} + +void gpxtrk_delete(struct gpxtrk * trk) +{ + int i; + if(trk==NULL) + return; + for (i=0; itrkpt_list_count; i++) + gpxpt_delete(trk->trkpt_list[i]); + xfree(trk->trkpt_list); + xfree(trk); +} + +struct gpx_data * gpx_data_new() +{ + struct gpx_data * all_data = (struct gpx_data *)xmalloc(sizeof(struct gpx_data)); + all_data->data_source_name=NULL; + all_data->wpt_list=NULL; + all_data->wpt_list_count=0; + all_data->rte_list=NULL; + all_data->rte_list_count=0; + all_data->trk_list=NULL; + all_data->trk_list_count=0; + return all_data; +} + +void gpx_data_delete(struct gpx_data * data) +{ + int i; + if(data==NULL) + return; + + xfree(data->data_source_name); + for (i=0; iwpt_list_count; i++) + gpxpt_delete(data->wpt_list[i]); + for (i=0; irte_list_count; i++) + gpxrte_delete(data->rte_list[i]); + for (i=0; itrk_list_count; i++) + gpxtrk_delete(data->trk_list[i]); + xfree(data->wpt_list); + xfree(data->rte_list); + xfree(data->trk_list); + xfree(data); +} + +void print_wptlist(struct gpxpt ** wpt_list, int wpt_list_count) +{ + int i; + printf("Global waypoints:\n"); + for (i=0; ilat, wpt_list[i]->lon, wpt_list[i]->name, wpt_list[i]->desc); +} + +void print_route(struct gpxrte * rte) +{ + int i; + printf("Route '%s' with %d route-points:\n", rte->name, rte->rtept_list_count); + for (i=0; irtept_list_count; i++) + printf("rtept: lat=%f, lon=%f, name='%s', desc='%s'\n", + (rte->rtept_list)[i]->lat, (rte->rtept_list)[i]->lon, + (rte->rtept_list)[i]->name, (rte->rtept_list)[i]->desc); +} + +void print_route_list(struct gpxrte ** rte_list, int rte_list_count) +{ + int i; + printf("Global route list with %d routes:\n", rte_list_count); + for (i=0; itrkpt_list_count); + for (i=0; itrkpt_list_count; i++) + printf("trkpt: lat=%f, lon=%f\n", + trk->trkpt_list[i]->lat, trk->trkpt_list[i]->lon); +} + +void print_track_list(struct gpxtrk ** trk_list, int trk_list_count) +{ + int i; + printf("Global track list with %d tracks:\n", trk_list_count); + for (i=0; iwpt_list, all_data->wpt_list_count); + print_route_list(all_data->rte_list, all_data->rte_list_count); + print_track_list(all_data->trk_list, all_data->trk_list_count); +} + +char* get_att(char* match, const char **atts) +{ + const char **avp = &atts[0]; + while (*avp) { + if (strcmp(avp[0], match) == 0) + return (char *)avp[1]; + avp+=2; + } + return NULL; +} + +void startunkn(void *userData, const char *name, const char **atts) +{ + if(opts.verbose_flag > 3) + printf("ignoring start element name %s\n", name); +} + +void endunkn(void *userData, const char *name) +{ + if(opts.verbose_flag > 3) + printf("ignoring end element name %s\n", name); +} + +void startwpt(void *userData, const char *name, const char **atts) +{ + struct gpx_data * dat = (struct gpx_data *)userData; + + if (current_main_element!=0) + { + printf("unexpected element\n"); + debug_pause(); + exit(1); + } + current_main_element=GPX_ELEM_TYPE_WPT; + + dat->wpt_list=(struct gpxpt **)xrealloc(dat->wpt_list, (dat->wpt_list_count+1)*sizeof(struct gpxpt *)); + dat->wpt_list[dat->wpt_list_count] = gpxpt_new(); + + sscanf(get_att("lat", atts), "%lf", &(dat->wpt_list[dat->wpt_list_count]->lat)); + sscanf(get_att("lon", atts), "%lf", &(dat->wpt_list[dat->wpt_list_count]->lon)); + dat->wpt_list_count++; +} + +void endwpt(void *userData, const char *name) +{ + if (current_main_element!=GPX_ELEM_TYPE_WPT) + { + printf("unexpected element\n"); + debug_pause(); + exit(1); + } + current_main_element=0; +} + +void startrte(void *userData, const char *name, const char **atts) +{ + struct gpx_data * dat = (struct gpx_data *)userData; + + if (current_main_element!=0) + { + printf("unexpected element\n"); + debug_pause(); + exit(1); + } + current_main_element=GPX_ELEM_TYPE_RTE; + + dat->rte_list=(struct gpxrte **)xrealloc(dat->rte_list, (dat->rte_list_count+1)*sizeof(struct gpxrte *)); + dat->rte_list[dat->rte_list_count]=gpxrte_new(); +// dat->rte_list[dat->rte_list_count]->name="{get route name from a following element}"; + dat->rte_list_count++; +} + +void endrte(void *userData, const char *name) +{ + if (current_main_element!=GPX_ELEM_TYPE_RTE) + { + printf("unexpected element\n"); + debug_pause(); + exit(1); + } + current_main_element=0; +} + +void startrtept(void *userData, const char *name, const char **atts) +{ + struct gpx_data * dat = (struct gpx_data *)userData; + struct gpxrte * thisrte = dat->rte_list[dat->rte_list_count-1]; + + if (current_main_element!=GPX_ELEM_TYPE_RTE) + { + printf("unexpected element\n"); + debug_pause(); + exit(1); + } + current_main_element=GPX_ELEM_TYPE_RTEPT; + + thisrte->rtept_list=(struct gpxpt **)xrealloc(thisrte->rtept_list, + (thisrte->rtept_list_count+1)*sizeof(struct gpxpt *)); + thisrte->rtept_list[thisrte->rtept_list_count] = gpxpt_new(); + sscanf(get_att("lat", atts), "%lf", &(thisrte->rtept_list[thisrte->rtept_list_count]->lat)); + sscanf(get_att("lon", atts), "%lf", &(thisrte->rtept_list[thisrte->rtept_list_count]->lon)); + thisrte->rtept_list_count++; +} + +void endrtept(void *userData, const char *name) +{ + if (current_main_element!=GPX_ELEM_TYPE_RTEPT) + { + printf("unexpected element\n"); + debug_pause(); + exit(1); + } + current_main_element=GPX_ELEM_TYPE_RTE; +} + +void starttrk(void *userData, const char *name, const char **atts) +{ + struct gpx_data * dat = (struct gpx_data *)userData; + + if (current_main_element!=0) + { + printf("unexpected element\n"); + debug_pause(); + exit(1); + } + current_main_element=GPX_ELEM_TYPE_TRK; + + dat->trk_list=(struct gpxtrk **)xrealloc(dat->trk_list, (dat->trk_list_count+1)*sizeof(struct gpxtrk *)); + dat->trk_list[dat->trk_list_count]=gpxtrk_new(); + dat->trk_list_count++; +} + +void endtrk(void *userData, const char *name) +{ +// struct gpx_data * dat = (struct gpx_data *)userData; + + if (current_main_element!=GPX_ELEM_TYPE_TRK) + { + printf("unexpected element\n"); + debug_pause(); + exit(1); + } + current_main_element=0; + +// printf("read end of track%d, with %d points\n", +// dat->trk_list_count, +// dat->trk_list[dat->trk_list_count-1]->trkpt_list_count); +} + +// just eat : we join all track segments as a single track + +void starttrkseg(void *userData, const char *name, const char **atts) +{ + if (current_main_element!=GPX_ELEM_TYPE_TRK) + { + printf("unexpected element\n"); + debug_pause(); + exit(1); + } + current_main_element=GPX_ELEM_TYPE_TRKSEG; +} + +void endtrkseg(void *userData, const char *name) +{ + if (current_main_element!=GPX_ELEM_TYPE_TRKSEG) + { + printf("unexpected element\n"); + debug_pause(); + exit(1); + } + current_main_element=GPX_ELEM_TYPE_TRK; +} + +void starttrkpt(void *userData, const char *name, const char **atts) +{ + struct gpx_data * dat = (struct gpx_data *)userData; + struct gpxtrk * thistrk = dat->trk_list[dat->trk_list_count-1]; + + if (current_main_element!=GPX_ELEM_TYPE_TRKSEG) + { + printf("unexpected element\n"); + debug_pause(); + exit(1); + } + current_main_element=GPX_ELEM_TYPE_TRKPT; + + thistrk->trkpt_list=(struct gpxpt **)xrealloc(thistrk->trkpt_list, + (thistrk->trkpt_list_count+1)*sizeof(struct gpxpt *)); + thistrk->trkpt_list[thistrk->trkpt_list_count]=gpxpt_new(); + sscanf(get_att("lat", atts), "%lf", &(thistrk->trkpt_list[thistrk->trkpt_list_count]->lat)); + sscanf(get_att("lon", atts), "%lf", &(thistrk->trkpt_list[thistrk->trkpt_list_count]->lon)); + thistrk->trkpt_list_count++; +} + +void endtrkpt(void *userData, const char *name) +{ + if (current_main_element!=GPX_ELEM_TYPE_TRKPT) + { + printf("unexpected element\n"); + debug_pause(); + exit(1); + } + current_main_element=GPX_ELEM_TYPE_TRKSEG; +} + +void startname(void *userData, const char *name, const char **atts) +{ +} + +void endname(void *userData, const char *name) +{ + struct gpx_data * dat = (struct gpx_data *)userData; + struct gpxrte* thisrte; +// struct gpxtrk* thistrk; + char* nameval = xrealloc(cdata, (cdata_length+1)*sizeof(XML_Char)); + nameval[cdata_length]=0; + cdata=NULL; + cdata_length=0; + str2ascii(nameval); + switch (current_main_element) + { + case GPX_ELEM_TYPE_WPT: + dat->wpt_list[dat->wpt_list_count-1]->name=nameval; + break; + case GPX_ELEM_TYPE_RTE: + dat->rte_list[dat->rte_list_count-1]->name=nameval; + break; + case GPX_ELEM_TYPE_RTEPT: + thisrte = dat->rte_list[dat->rte_list_count-1]; + thisrte->rtept_list[thisrte->rtept_list_count-1]->name=nameval; + break; + case GPX_ELEM_TYPE_TRK: +// thistrk = dat->trk_list[dat->trk_list_count-1]; +// thistrk->trkpt_list[thistrk->trkpt_list_count-1]->name=nameval; + //break; + case GPX_ELEM_TYPE_TRKSEG: + //break; + case GPX_ELEM_TYPE_TRKPT: + default: + xfree(nameval); + break; + } +} + +void startdesc(void *userData, const char *name, const char **atts) +{ +} + +void enddesc(void *userData, const char *name) +{ + struct gpx_data * dat = (struct gpx_data *)userData; +// struct gpxrte* thisrte; +// struct gpxtrk* thistrk; + char* desc = xrealloc(cdata, cdata_length+1); + desc[cdata_length]=0; + cdata=NULL; + cdata_length=0; + str2ascii(desc); + switch (current_main_element) + { + case GPX_ELEM_TYPE_WPT: + str2ascii(desc); + dat->wpt_list[dat->wpt_list_count-1]->desc=desc; + break; + case GPX_ELEM_TYPE_RTE: +// dat->rte_list[dat->rte_list_count-1]->desc=desc; +// break; + case GPX_ELEM_TYPE_RTEPT: +// thisrte = dat->rte_list[dat->rte_list_count-1]; +// thisrte->rtept_list[thisrte->rtept_list_count-1]->desc=desc; +// break; + case GPX_ELEM_TYPE_TRK: +// thistrk = dat->trk_list[dat->trk_list_count-1]; +// thistrk->trkpt_list[thistrk->trkpt_list_count-1]->desc=desc; +// break; + case GPX_ELEM_TYPE_TRKSEG: +// break; + case GPX_ELEM_TYPE_TRKPT: + default: + xfree(desc); + break; + } +} + +void startsrc(void *userData, const char *name, const char **atts) +{ +} + +void endsrc(void *userData, const char *name) +{ +} + +#define GPX_NUM_ELEM_HANDLERS 10 + +gpx_elm_start_handler gpx_start_elm_handler[] = +{ + &startunkn, + &startwpt, + &startrte, + &startrtept, + &starttrk, + &starttrkseg, + &starttrkpt, + &startname, + &startdesc, + &startsrc +}; + +gpx_elm_end_handler gpx_end_elm_handler[] = +{ + &endunkn, + &endwpt, + &endrte, + &endrtept, + &endtrk, + &endtrkseg, + &endtrkpt, + &endname, + &enddesc, + &endsrc +}; + + +int get_gpx_type_ndx(const char* type_name) +{ + int i; + for (i=1; idata_source_name=(char*)xmalloc(strlen(gpx_in_file_name)+1); + strcpy(all_data->data_source_name, gpx_in_file_name); + + XML_SetUserData(parser, all_data); + XML_SetElementHandler(parser, startElement, endElement); + XML_SetCharacterDataHandler(parser, CharacterData); + + if(gpx_in_file_name==NULL) + { + fprintf(stderr, "Unexpected null filename for gpx_in_file_name\n"); + debug_pause(); + exit(1); + } + else + { + printf("Importing data from %s\n", gpx_in_file_name); + gpx_in_file = fopen(gpx_in_file_name, "r"); + } + + if(gpx_in_file==NULL) + { + fprintf(stderr, "Unable to open GPX file %s\n", gpx_in_file_name); + debug_pause(); + exit(1); + } + + do + { + size_t len = fread(buf, 1, sizeof(buf), gpx_in_file); + done = len < sizeof(buf); + if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR) + { + fprintf(stderr, + "%s at line %d\n", + XML_ErrorString(XML_GetErrorCode(parser)), + XML_GetCurrentLineNumber(parser)); + return all_data; + } + } while (!done); + XML_ParserFree(parser); + + if (opts.verbose_flag > 2) + { + } + + xfree(cdata); + + return all_data; +} diff --git a/st2gpx/src/readmpst.c b/st2gpx/src/readmpst.c new file mode 100644 index 000000000..3a75d30cb --- /dev/null +++ b/st2gpx/src/readmpst.c @@ -0,0 +1,400 @@ +/* + readmpst.c + + Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format. + + Copyright (C) 2003 James Sherring, james_sherring@yahoo.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + + This app depends on istorage & istorage-make from Pabs (pabs3@zip.to) + and James Clark's Expat xml parser from http://www.libexpat.org/. + +*/ +#include +#include +#include + +#include "st2gpx.h" +#include "gpx.h" + +#define STATUS_BOF 1 +#define STATUS_EOF 2 +#define STATUS_FILE_HEADER 3 + +#define STATUS_WPT_LIST_HEADER 4 +#define STATUS_WPT_LIST_BODY 5 + +#define STATUS_RTE_LIST_HEADER 6 +#define STATUS_RTE_ITEM 7 +#define STATUS_RTE_PT_LIST_HEADER 8 +#define STATUS_RTE_PT_LIST_BODY 9 + +#define STATUS_TRK_LIST_HEADER 10 +#define STATUS_TRK_ITEM 11 +#define STATUS_TRK_PT_LIST_HEADER 12 +#define STATUS_TRK_PT_LIST_BODY 13 + +#define MAX_FIELD_WIDTH 50 +// I have files with 1300 lines +#define MAX_LINES 10000 +//#define MAX_LINES 200 + +//#define MAX_FIELDS 20; +//char* list_header_fieldnames[MAX_FIELDS]; +//char* list_header_values[MAX_FIELDS]; +//char* list_fieldnames[MAX_FIELDS]; +//char* list_values[MAX_FIELDS]; + +const char* garmin_16_symbols[16]= +{ + "Waypoint", + "Residence", + "Gas Station", + "Car", + "Fishing Area", + "Boat Ramp", + "Marina", + "Shipwreck", + "Exit", + "Skull and Crossbones", + "Flag", + "Campground", + "Circle with X", + "Hunting Area", + "Medical Facility", + "TrackBack Point" +}; + +struct gpx_data * read_mpstext(char* mpstxt_file_name) +{ + char line_buf[1001]; + FILE* mpstxt_file = fopen(mpstxt_file_name, "r"); + //int byte_read; + int status=STATUS_FILE_HEADER; + int last_status=STATUS_BOF; + int this_blank=0; + int last_blank=0; + char * fgets_status; + int parsed_vars=0; + + int loop_count=0; + + // being lazy a lot of large variables + char f_Name[ MAX_FIELD_WIDTH ]; + char f_Desc[ MAX_FIELD_WIDTH ]; + char f_Type[ MAX_FIELD_WIDTH ]; + char f_lat_dir; + double f_lat; + char f_lon_dir; + double f_lon; + char f_Altitude[ MAX_FIELD_WIDTH ]; + char f_Depth[ MAX_FIELD_WIDTH ]; + char f_Proximity[ MAX_FIELD_WIDTH ]; + char f_DisplayMode[ MAX_FIELD_WIDTH ]; + char f_Color[ MAX_FIELD_WIDTH ]; + char f_Symbol[ MAX_FIELD_WIDTH ]; + char f_Facility[ MAX_FIELD_WIDTH ]; + char f_City[ MAX_FIELD_WIDTH ]; + char f_State[ MAX_FIELD_WIDTH ]; + char f_Country[ MAX_FIELD_WIDTH ]; + + char f_Length[ MAX_FIELD_WIDTH ]; + char f_Course[ MAX_FIELD_WIDTH ]; + char Waypoints[ MAX_FIELD_WIDTH ]; + + char f_WaypointName[ MAX_FIELD_WIDTH ]; + char f_Distance[ MAX_FIELD_WIDTH ]; + char f_LegLength[ MAX_FIELD_WIDTH ]; + + char f_StartTime[ MAX_FIELD_WIDTH ]; + char f_ElapsedTime[ MAX_FIELD_WIDTH ]; + char f_AverageSpeed[ MAX_FIELD_WIDTH ]; + char f_DateTime[ MAX_FIELD_WIDTH ]; + char f_LegTime[ MAX_FIELD_WIDTH ]; + char f_LegSpeed[ MAX_FIELD_WIDTH ]; + char f_LegCourse[ MAX_FIELD_WIDTH ]; + + struct gpx_data * dat = gpx_data_new(); + struct gpxpt * this_gpxpt=NULL; + struct gpxpt * matching_wpt=NULL; + struct gpxrte * thisrte=NULL; + + dat->data_source_name=(char*)xmalloc(strlen(mpstxt_file_name)+1); + strcpy(dat->data_source_name, mpstxt_file_name); + + if (mpstxt_file==NULL) + { + printf("Error opening MapSource text file %s for input\n", mpstxt_file_name); + debug_pause(); + exit(1); + } + else + printf("Reading MapSource text file %s\n", mpstxt_file_name); + + while (status!=STATUS_EOF) + { + fgets_status = fgets((char*)line_buf, 1000, mpstxt_file); + if (fgets_status==NULL) + status=STATUS_EOF; + + //printf("read %d bytes in line: %s\n", bytes_read, line_buf); + + if (strcmp(line_buf,"\n")==0) + this_blank=1; + else + this_blank=0; + + switch(status) + { + case STATUS_FILE_HEADER: + // Just eat all header lines until a this_blank line + // We should verify this header + + // FIXME We need to check that Grid=Lat/Lon hddd.ddddd° + // to be sure we can read the data + if (this_blank) + status=STATUS_WPT_LIST_HEADER; + break; + + case STATUS_WPT_LIST_HEADER: + // check type & set proper status + if (this_blank) + status=STATUS_WPT_LIST_BODY; + break; + + case STATUS_WPT_LIST_BODY: + if (this_blank) + { + status=STATUS_RTE_LIST_HEADER; + } + else + { + parsed_vars=sscanf(line_buf, "Waypoint\t%[^\t]\t%[^\t]\t%[^\t]\t%c%lf %c%lf\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]", + &f_Name, &f_Desc, &f_Type, &f_lat_dir, &f_lat, &f_lon_dir, &f_lon, &f_Altitude, + &f_Depth, &f_Proximity, &f_DisplayMode, &f_Color, &f_Symbol, &f_Facility, + &f_City, &f_State, &f_Country); + if (parsed_vars<4) + { + printf("Error parsing line %d as a waypoint. Need at least 4 vars, only got %d\n", + loop_count+1, parsed_vars); + printf("Problem line is: %s\n", line_buf); + } + else + { + dat->wpt_list=(struct gpxpt **)xrealloc(dat->wpt_list, (dat->wpt_list_count+1)*sizeof(struct gpxpt *)); + this_gpxpt = dat->wpt_list[dat->wpt_list_count] = gpxpt_new(); + + if (f_lat_dir=='S') + f_lat=-f_lat; + else if(f_lat_dir!='N') + printf("Error parsing line %d as a waypoint. '%c' when expecting 'N' or 'S' for latitdue.\n", f_lat_dir); + + if (f_lon_dir=='W') + f_lon=-f_lon; + else if(f_lon_dir!='E') + printf("Error parsing line %d as a waypoint. '%c' when expecting 'E' or 'W' for longitude.\n", f_lat_dir); + + this_gpxpt->lat = f_lat; + this_gpxpt->lon = f_lon; + this_gpxpt->name=xmalloc(strlen(f_Name)+1); + strcpy(this_gpxpt->name, f_Name); + str2ascii(this_gpxpt->name); + this_gpxpt->desc=xmalloc(strlen(f_Desc)+1); + strcpy(this_gpxpt->desc, f_Desc); + str2ascii(this_gpxpt->desc); + dat->wpt_list_count++; + } + } + break; + + case STATUS_RTE_LIST_HEADER: + // check type & set proper status + if (this_blank && !last_blank) + status=STATUS_RTE_ITEM; + break; + + case STATUS_RTE_ITEM: + if (this_blank) + { + if (last_blank) + status=STATUS_TRK_LIST_HEADER; + else + status=STATUS_RTE_PT_LIST_HEADER; + } + else + { + parsed_vars=sscanf(line_buf, "Route\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]", + &f_Name, &f_Length, &f_Course, &Waypoints); + if (parsed_vars<1) + { + printf("Error parsing line %d as a route. Need at least 1 var, only got %d\n", + loop_count+1, parsed_vars); + printf("Problem line is: %s\n", line_buf); + } + else + { + dat->rte_list=(struct gpxrte **)xrealloc(dat->rte_list, (dat->rte_list_count+1)*sizeof(struct gpxrte *)); + dat->rte_list[dat->rte_list_count]=gpxrte_new(); + dat->rte_list[dat->rte_list_count]->name = xmalloc(strlen(f_Name)+1); + str2ascii(f_Name); + strcpy(dat->rte_list[dat->rte_list_count]->name, f_Name); + dat->rte_list_count++; + } + } + break; + + case STATUS_RTE_PT_LIST_HEADER: + if (this_blank) + status=STATUS_RTE_PT_LIST_BODY; + break; + + case STATUS_RTE_PT_LIST_BODY: + if (this_blank) + //loop back to another new route + status=STATUS_RTE_ITEM; + else + { + parsed_vars=sscanf(line_buf, "Route Waypoint\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]", + &f_WaypointName, &f_Distance, &f_LegLength, &f_Course); + if (parsed_vars<1) + { + printf("Error parsing line %d as a routepoint. Need at least 1 var, only got %d\n", + loop_count+1, parsed_vars); + printf("Problem line is: %s\n", line_buf); + } + else + { + matching_wpt=find_matching_wpt(dat, f_WaypointName); + if (matching_wpt == NULL) + { + printf("Ignoring routepoint %s because I cant match it to any waypoints\n", + f_WaypointName); + } + else + { + thisrte = dat->rte_list[dat->rte_list_count-1]; + thisrte->rtept_list=(struct gpxpt **)xrealloc(thisrte->rtept_list, + (thisrte->rtept_list_count+1)*sizeof(struct gpxpt *)); + this_gpxpt = thisrte->rtept_list[thisrte->rtept_list_count] = gpxpt_copy(matching_wpt); + thisrte->rtept_list_count++; + } + } + } + break; + + case STATUS_TRK_LIST_HEADER: + // check type & set proper status + if (this_blank && !last_blank) + status=STATUS_TRK_ITEM; + break; + + case STATUS_TRK_ITEM: + if (this_blank) + { + if (last_blank) + status=STATUS_EOF; + else + status=STATUS_TRK_PT_LIST_HEADER; + } + else + { + parsed_vars=sscanf(line_buf, "Track\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]", + &f_Name, &f_StartTime, &f_ElapsedTime, &f_Length, &f_AverageSpeed); + if (parsed_vars<1) + { + printf("Error parsing line %d as a Track. Need at least 1 var, only got %d\n", + loop_count+1, parsed_vars); + printf("Problem line is: %s\n", line_buf); + } + else + { + dat->trk_list=(struct gpxtrk **)xrealloc(dat->trk_list, + (dat->trk_list_count+1)*sizeof(struct gpxtrk *)); + dat->trk_list[dat->trk_list_count]=gpxtrk_new(); + //dat->trk_list[dat->trk_list_count]->name = (char*)malloc(strlen(f_Name)+1); + //strcpy(dat->trk_list[dat->trk_list_count]->name, f_Name); + dat->trk_list_count++; + } + } + break; + + case STATUS_TRK_PT_LIST_HEADER: + if (this_blank) + status=STATUS_TRK_PT_LIST_BODY; + break; + + case STATUS_TRK_PT_LIST_BODY: + if (this_blank) + // loop back for another new track + status=STATUS_TRK_ITEM; + else + { + parsed_vars=sscanf(line_buf, "Trackpoint\t%c%lf %c%lf\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]", + &f_lat_dir, &f_lat, &f_lon_dir, &f_lon, &f_DateTime, &f_Altitude, + &f_Depth, &f_LegLength, &f_LegTime, &f_LegSpeed, &f_LegCourse); + if (parsed_vars<4) + { + printf("Error parsing line %d as a track-point. Need at least 4 vars, only got %d\n", + loop_count+1, parsed_vars); + printf("Problem line is: %s\n", line_buf); + } + else + { + struct gpxtrk * thistrk = dat->trk_list[dat->trk_list_count-1]; + thistrk->trkpt_list=(struct gpxpt **)xrealloc(thistrk->trkpt_list, + (thistrk->trkpt_list_count+1)*sizeof(struct gpxpt *)); + thistrk->trkpt_list[thistrk->trkpt_list_count]=gpxpt_new(); + + if (f_lat_dir=='S') + f_lat=-f_lat; + else if(f_lat_dir!='N') + printf("Error parsing line %d as a waypoint. '%c' when expecting 'N' or 'S' for latitdue.\n", f_lat_dir); + + if (f_lon_dir=='W') + f_lon=-f_lon; + else if(f_lon_dir!='E') + printf("Error parsing line %d as a waypoint. '%c' when expecting 'E' or 'W' for longitude.\n", f_lat_dir); + + thistrk->trkpt_list[thistrk->trkpt_list_count]->lat=f_lat; + thistrk->trkpt_list[thistrk->trkpt_list_count]->lon=f_lon; + thistrk->trkpt_list_count++; + } + } + break; + + default: + {; + } + } + + last_status=status; + last_blank=this_blank; + + loop_count++; + if (loop_count>MAX_LINES) + { + printf("Read %d input lines, which seems rather high\n", loop_count); + break; + } + + } + + if(opts.verbose_flag>4) + print_gpx_data(dat); + + return dat; +} diff --git a/st2gpx/src/st2gpx license.txt b/st2gpx/src/st2gpx license.txt new file mode 100644 index 000000000..5068e4342 --- /dev/null +++ b/st2gpx/src/st2gpx license.txt @@ -0,0 +1,23 @@ +st2gpx + +Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format. + +Copyright (C) 2003 James Sherring, james_sherring@yahoo.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + +st2gpx depends on istorage & istorage-make from Pabs (pabs3@zip.to) +and James Clark's Expat xml parser from http://www.libexpat.org/. diff --git a/st2gpx/src/st2gpx.c b/st2gpx/src/st2gpx.c index 8b5c17a75..66ff4d1e9 100644 --- a/st2gpx/src/st2gpx.c +++ b/st2gpx/src/st2gpx.c @@ -1,5 +1,5 @@ /* - st2gpxmain.c + st2gpx.c Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format. @@ -20,740 +20,146 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA -History: + This app depends on istorage & istorage-make from Pabs (pabs3@zip.to) + and James Clark's Expat xml parser from http://www.libexpat.org/. -21-10-2003 annotations stream dump -27-10-2003 journey & pushpins using VB module - 8-11-2003 match journey route-points to pushpins, - integrate parts into singel C/C++ exe (except istorage) - 9-11-2003 fixed invalid gpx - -To do: - Get lat & lon for journey route points not matched to pushpins - Get point info for non-line annotations, e.g. text boxes. - Import functionality - Implement using platform independant libraries. - -bugs: - unable to delete UserData file after accessing with ADO. */ #include #include -#include #include #include #include +#include +#include + + // #include #include "getopt.h" +#include "gpx.h" +#include "st2gpx.h" +#include "annotations.h" +#include "journey.h" +#include "properties.h" +#include "contents.h" +#include "ppinutil.h" #include "pushpins.h" -#ifndef M_PI -#define M_PI 3.1415926535 -#endif - -#define JOUR_FILE_HEAD_LEN 32 -#define JOUR_FILE_TAIL_LEN 430 -// + text1 +2*text2 -#define JOUR_WPTREC_LEN 121 - -#define JOUR_FILEOS_NUMREC 16 - -#define JOURWPT_REC_HEAD_LEN 41 - -#define JOURWPT_RECOS_WPTNUM 0 -#define JOURWPT_RECOS_STR1LEN 40 -#define JOURWPT_RECOS_STR1 41 -// + val(JOURWPT_RECOS_STR1LEN) -#define JOURWPT_RECOS_STR2LEN 44 -#define JOURWPT_RECOS_STR2 45 - -#define ANNOT_FILE_HEAD_LEN 12 -// This needs to be long enough to get enough params to decide which record, -// but no biger than the shortest record -#define ANNOT_REC_HEAD_LEN 57 //19 - -#define ANNOT_TYPE_LINE 0 -#define ANNOT_TYPE_OVAL 1 -#define ANNOT_TYPE_TEXT 2 -#define ANNOT_TYPE_CIRCLE 3 - -#define REC_CLOSE_LEN 0 -// offsets for parameters in annotation recods -#define ANNOT_RECOS_TYPE 0 -#define ANNOT_RECOS_ANUM 4 -#define ANNOT_RECOS_TEXTLEN 20 -#define ANNOT_RECOS_TEXT 24 -#define ANNOT_RECOS_LINENUMPOINTS 53 -#define ANNOT_RECOS_LINEJOINFLAG 48 -#define ANNOT_RECOS_XSCALE 48 -#define ANNOT_RECOS_YSCALE 52 - -#define GPX_HEADER1 "\n\n" -#define GPX_THIS_PROGRAM "st2gpx from james_sherring@yahoo.com" -#define GPX_FOOTER "" - -#define GPX_WPT 0 -#define GPX_RTEPT 1 -#define GPX_TRKPT 2 - -/* -typedef struct annotationbuf -{ - int annot_num; - int flags; // bit fields in first byte - int unkn1; // normally 0 - int unkn2; // ? seems to have byte fields - int text_len; - // + 2*text_len bytes of text here - int fill_color; // seems to have byte fields. First byte is fill, other bytes are strange - int line_color; - int line_thickness; // 20 times the point-size - int arrow_type; // 00=none, 01=left, 02=right, 03=both - int unkn3; - int joinflag; // 0 line does not join, 1, joins. Not sure what large balues for non-lines mean - xscale? - char unkn4; // y-scale? - int num_points; // different meaning for non-lines -} structannotationbuf; -*/ - -typedef struct jourwpt_rec -{ - int jour_num; - int text1_length; - char* text1; - int text2_length; - char* text2; - long UdId; - struct pushpin* pushpin; - int buf_length; - char* buf; -} tag_jour_rec; - -typedef struct gpx_point -{ - float lat; - float lon; - float height; -} tag_gpx_point; - -typedef char* annot_file_header; -typedef char* annot_rec_header; -typedef char* annot_buf; - -typedef struct annot_rec -{ - int type; - int length; - char* buf; - int annot_num; - int text_length; - char* text; - int line_points; -} tag_annot_rec; - -struct point { - double lon; - double lat; -} tag_point; - -struct ms_point { - long grid; - long precision; -} tag_ms_point; - - -// Also need to include variable text length + line-points with these -int annot_rec_len[4]={57, 868, 124, 868}; -int annot_head_len[4]={57, 48, 48, 48}; -char* annot_type_name[4]={"Line", "Oval", "Textbox", "Circle"}; -static char* gpxptypelabel[] = {"wpt", "rtept", "trkpt"}; - -// constants for converting from MS Grid & Precision to latitude and longitude -double magic1 = 182.044444444444; -double magic2 = 0x10000; - -// Args set by getopt etc - -FILE* ppin_file=NULL; -FILE* jour_file=NULL; -FILE* annot_file=NULL; -FILE* gpx_file=NULL; -char* source_file_name=NULL; - -/* Flag set by --verbose. */ -// 0 - only errors -// 1 also the structured data output, e.g. line point info -// 2 also record types & parameters -// 3 also detailed summary info -// 4 also detailed analysis of headers & record params -// 5 also dump buffers -// 6 lots of debug info -static int verbose_flag = 2; -static int explore_flag = 0; -// force line-type annotations to be exported as GPX routes instead of tracks -static int use_gpx_route = 0; - -// std_anotfile_header[8,9] are variable (number of annotations) -char std_annotfile_header[ANNOT_FILE_HEAD_LEN] = - {0x34, 0x12, 0x00, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}; +struct st2gpx_options opts; void * xmalloc(size_t size) { - void *obj = malloc(size); - if (!obj) + void *obj; + if (size<0) { - fprintf(stderr, "Unable to allocate %d bytes of memory.\n", size); + fprintf(stderr, "**** Error: trying to malloc %d bytes ****/n"); + debug_pause(); + exit(-1); } - return obj; -} - -void * xrealloc(void* ptr, size_t size) -{ - void *obj = realloc(ptr, size); +//#ifdef _DEBUG +// obj = _malloc_dbg(size, _NORMAL_BLOCK, __FILE__, __LINE__ ); +//#else + obj = malloc(size); +//#endif if (!obj) { - fprintf(stderr, "Unable to (re)allocate %d bytes of memory.\n", size); + fprintf(stderr, "Unable to allocate %d bytes of memory.\n", size); + debug_pause(); + exit(-1); } - return obj; -} -int fixhex(char c) -{ -// gcc (version?) does not print single byte hex vaues properly -// eg 0xe3 prints as 0xFFFFFFE3 -// this is only a problem for values above 0x80 -// Or maybe that is the proper handling of unsigned? -// Aaaahhh. I should use %u for printing unsigned... but the hex problem is still there - if(c & 0x80) - { - return ((int)c-0xFFFFFF00); - } else - return c; -} +#ifdef _DEBUG +#ifdef MEMTRACE + printf("Malloc'd %d bytes at %lx\n", size, obj); +#endif +#endif -void printbuf(char* buf, int len) -{ -// unsigned i; - int i; - printf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n"); - printf(" -----------------------------------------------"); - for(i=0; i> i; - lon_val += (lon_mask & msp.grid) >> (i+1); - lat_mask <<= 2; - lon_mask <<= 2; - } - - //printf("so far, lat_val=%d, lon_val=%d\n",lat_val ,lon_val); - - // Dont divide by magic1 until accounting for precision, - // because that would introduce rounding errors - p.lat = (double) lat_val ;// magic1; - p.lon = (double) lon_val ;// magic1; - - //printf("so far, got lat= %f lon= %f\n", p.lat, p.lon); - - lat_mask=1; - lon_mask=2; - lat_val=0; - lon_val=0; - - for (i=0; i<16; i++) { - lat_val += (lat_mask & msp.precision) >> i; - lon_val += (lon_mask & msp.precision) >> (i+1); - lat_mask <<= 2; - lon_mask <<= 2; - } - - //printf("so far, lat_val=%d, lon_val=%d\n",lat_val ,lon_val); - - p.lat += (double) lat_val / (magic2); - p.lon += (double) lon_val / (magic2); - - p.lat *= 1/ (magic1); - p.lon *= 1/ (magic1); - - //printf("so far, got lat= %f lon= %f\n", p.lat, p.lon); - - if (p.lon > 180) p.lon -= 360; - if (p.lat > 180) p.lat -= 360; - return p; -} - -void explore_annot(struct annot_rec rec) -{ - char* header; - char* tail; - int taillength; - - header = (char*)xmalloc(ANNOT_REC_HEAD_LEN); - memcpy(header, rec.buf, ANNOT_RECOS_TEXT); - memcpy(header+ANNOT_RECOS_TEXT+2*rec.text_length, rec.buf, - ANNOT_REC_HEAD_LEN-ANNOT_RECOS_TEXT); - - tail = rec.buf+ANNOT_REC_HEAD_LEN+2*rec.text_length; - taillength = rec.length - ANNOT_REC_HEAD_LEN+2*rec.text_length; - - printf("Record buffer\n", annot_type_name[rec.type]); - printbuf(rec.buf, rec.length); - printf("Record high buffer\n", annot_type_name[rec.type]); - printbufhigh(rec.buf, rec.length); - printf("Record wide header:\n", annot_type_name[rec.type]); - printbufwide(header, ANNOT_REC_HEAD_LEN); - printf("Record tail:\n"); - printbuf(tail, taillength); - printf("Record wide tail:\n"); - printbufwide(tail, taillength); - printf("Record tail as floats:\n"); - printbufasfloat(tail, taillength); - printf("Record tail as points:\n"); - printbufaspoints(tail, taillength); -// if (rec.type == ANNOT_TYPE_TEXT) -// { - //printfloatbuf((float*)(tail+3), taillength/4 -1); -// } -// else if (rec.type == ANNOT_TYPE_OVAL ) -// printfloatbuf((float*)(tail+3), taillength/4 -1); -// else if (rec.type == ANNOT_TYPE_CIRCLE )) -// printfloatbuf((float*)(tail+3), taillength/4 -1); - free(header); -} - -void gpx_open_write_file_header(char* gpx_file_name) -{ - if (gpx_file_name) - { - gpx_file = fopen(gpx_file_name, "w"); - if (gpx_file == NULL) + // FIXME saxcount complains that 0x1c is an invalid character, what else?? + if ( (ustr[i]>127) || (ustr[i]==0x1c) ) { - fprintf(stderr, "Cannot open %s\n", optarg); - exit(1); + printf("Converting non-ascii char %c to space.\n", ustr[i]); + str[i]=' '; } - } - else - return; - - if (gpx_file!=NULL) - { - fprintf(gpx_file, GPX_HEADER1); - fprintf(gpx_file, GPX_HEADER2); - if (source_file_name) - fprintf(gpx_file, "\t=\"This file was created from %s by %s\"\n", - source_file_name, GPX_THIS_PROGRAM); - // Some more tags we should add here - // Descriptive name of the GPX file - // Description of the GPX file - // Name of the file's creator - // \n\t\n"); - - case ANNOT_TYPE_OVAL: - case ANNOT_TYPE_TEXT: - case ANNOT_TYPE_CIRCLE: - default: - break; - } + int len1=strlen(str1); + int len2=strlen(str2); + char* nw = (char*)xmalloc(len1 + len2 +1); + strcpy(nw, str1); + strcpy(nw+len1, str2); + return nw; } int readbytes(FILE* file, char* buf, int bytes2read) { - // cant I just do this with fread? int i; -// int status; -/* int readbyte; - for (i=0; i 5) - { - //printf("read byte from file %#x=%u=%c\n", readbyte,readbyte,readbyte); - //fflush(stdout); - - } - } -*/ i = fread(buf, 1, bytes2read, file); if (i 5) + if (opts.verbose_flag > 5) { printf("Readbytes: Read %d bytes from file\n",bytes2read); printbuf(buf, bytes2read); fflush(stdout); - if (gpx_file) - fflush(gpx_file); - } return(i); } -struct annot_rec read_annot_rec(int annot_num) -{ - // new improved version! - - int status; - int i; - struct annot_rec rec; - rec.buf = (char*)xmalloc(ANNOT_REC_HEAD_LEN); - // This read can fail because I have miscalculated number of records - // So exit gracefully - status = readbytes(annot_file, rec.buf, ANNOT_REC_HEAD_LEN); - if (status!=ANNOT_REC_HEAD_LEN) - { - gpx_write_file_trailer(); - // exit(1) - // should do some cleaning up here - return rec; - } - - rec.type = *(int*)(rec.buf+ANNOT_RECOS_TYPE); - rec.annot_num = *(int*)(rec.buf+ANNOT_RECOS_ANUM); - rec.text_length = *(int*)(rec.buf+ANNOT_RECOS_TEXTLEN); - rec.line_points=0; - if (rec.type == ANNOT_TYPE_LINE) - rec.line_points = *(int*)(rec.buf+ANNOT_RECOS_LINENUMPOINTS); - rec.length = annot_rec_len[rec.type] + 2*rec.text_length + 12*rec.line_points; - - printf("Got annotation %d with internal id %d, of type %s, text length %d, and %d line points\n", - annot_num+1, rec.annot_num, annot_type_name[rec.type], - rec.text_length, rec.line_points); - - rec.buf = (char*)xrealloc(rec.buf, rec.length); - status = readbytes(annot_file, rec.buf+ANNOT_REC_HEAD_LEN, rec.length - ANNOT_REC_HEAD_LEN); - if (status!=(rec.length - ANNOT_REC_HEAD_LEN)) - { - gpx_write_file_trailer(); - exit(1); - } - - if(rec.text_length>0) - { - rec.text=(char*)xmalloc(rec.text_length+1); - rec.text[rec.text_length]=0x0; - for (i=0;i 1) - - printf("The sb text in the box is: %s\n", rec.text); - } - - if (verbose_flag > 4) - { - printf("Recognised record with length %i\n",rec.length); - printbuf(rec.buf, rec.length); - } - - return rec; -} - -void process_annotations_stream(char* annot_file_name) -{ - // Read the annotation file header - - int i; - int num_annotations; -// int file_pos = ANNOT_FILE_HEAD_LEN; - annot_file_header file_header = (annot_file_header)xmalloc(ANNOT_FILE_HEAD_LEN); - int status; - struct annot_rec rec; - char* checkEOF; - - if ((annot_file = fopen(annot_file_name, "rb")) == NULL) - { - fprintf(stderr, "Quitting because I cannot open %s\n", annot_file_name); - exit(1); - } - - status=readbytes(annot_file, file_header, ANNOT_FILE_HEAD_LEN); - if (status!=ANNOT_FILE_HEAD_LEN) - { - printf("Cant make any more sense of annotations stream, continuing\n"); - return; - } - - // file_pos is for debugging only - - for (i=1; i<8; i++) - if ( file_header[i] != std_annotfile_header[i] ) - printf("Nonstandard annotations file header, header[%i]=0x%x, normal value is 0x%x\n", - i, file_header[i], std_annotfile_header[i] ); - - num_annotations = *(int*)(file_header+8); - - if (verbose_flag > 1) - { - printf("Annotations file header indicates %i annotations in file\n", - num_annotations); - } - - if (verbose_flag > 4) - { - printf("Dumping file header:\n"); - printbuf(file_header, ANNOT_FILE_HEAD_LEN); - } - - /* - ** Read all the annotation records - */ - for (i=0; i < num_annotations; i++) - { - rec = read_annot_rec(i); - - if (explore_flag) - explore_annot(rec); - - gpx_write_annot_rec(rec); - - free(rec.buf); - if (rec.text_length>0) - free(rec.text); - } - - // Check that we are at the end of annotation file - - checkEOF = xmalloc(4); - status=readbytes(annot_file, checkEOF, 4); - if ( (status!=4) || (checkEOF[0]!=0) || (checkEOF[1]!=0) - || (checkEOF[2]!=0) || (checkEOF[3]!=0) || (getc(annot_file)!=EOF) ) - { - fprintf (stderr, "Did not finish reading annotation file at EOF\n"); - if (gpx_file) - fprintf(gpx_file, GPX_FOOTER); - } - free(checkEOF); - fclose(annot_file); - fflush(stdout); - fflush(gpx_file); -} - -struct jourwpt_rec * read_journey_rec(int jour_num) -{ - int i; - int status; - int readlen1 = JOURWPT_REC_HEAD_LEN; - int readlen2; - int readlen3; - char c; - struct jourwpt_rec * rec = (struct jourwpt_rec *)xmalloc(sizeof(struct jourwpt_rec)); - - rec->buf = (char*)xmalloc(readlen1); - - status = readbytes(jour_file, rec->buf, readlen1); - if (status!=readlen1) - { - printf("Unexpected EOF while reading Journey route point %d part 1.\n", jour_num); - printf("Dumping Journey route point buffer read so far\n"); - printbuf(rec->buf, status); - //FIXME free rec - return NULL; - } - - // FIXME careful here - c = rec->buf[0]; - rec->UdId = c; - - c = rec->buf[JOURWPT_RECOS_STR1LEN]; - - rec->text1_length = (int)c; - - if (verbose_flag > 5) - { - printf("Reading Journey routepoint, got buf part1, text1 len = %d\n", - rec->text1_length); - printbuf(rec->buf, readlen1); - } - - readlen2 = rec->text1_length+4; - - rec->buf = (char*)xrealloc(rec->buf, readlen1 + readlen2); - status = readbytes(jour_file, rec->buf+readlen1, readlen2); - if (status!=readlen2) - { - printf("Unexpected EOF while reading Journey route point %d part 2.\n", jour_num); - printf("Dumping Journey route point buffer read so far\n"); - printbuf(rec->buf, readlen1+status); - //FIXME free rec - return NULL; - } - - c = rec->buf[JOURWPT_RECOS_STR2LEN + rec->text1_length]; - rec->text2_length = (int)c; - rec->buf_length = JOUR_WPTREC_LEN + rec->text1_length + 2*rec->text2_length; - - if (verbose_flag > 5) - { - printf("got buf part2, text2 len = %d\n", rec->text2_length); - printbuf(rec->buf, readlen1 + readlen2); - } - readlen3 = rec->buf_length - readlen1 - readlen2; - - rec->buf = (char*)xrealloc(rec->buf, rec->buf_length); - status = readbytes(jour_file, rec->buf+readlen1+readlen2, readlen3); - if (status!=readlen3) - { - printf("Unexpected EOF while reading Journey route point %d part 3.\n", jour_num); - printf("Dumping Journey route point buffer read so far\n"); - printbuf(rec->buf, readlen1+readlen2+status); - //FIXME free rec - return NULL; - } - - rec->text1=(char*)xmalloc(rec->text1_length+1); - rec->text2=(char*)xmalloc(rec->text2_length+1); - rec->text1[rec->text1_length]=0; - rec->text2[rec->text2_length]=0; - memcpy(rec->text1, rec->buf+JOURWPT_RECOS_STR1, rec->text1_length); - for (i=0; itext2_length; i++) - rec->text2[i]=rec->buf[JOURWPT_RECOS_STR2 + rec->text1_length+2*i]; - - if (verbose_flag > 3) - printf("got Journey routepoint UdId %d, text1 '%s', text2 '%s', length %d\n", - rec->UdId, rec->text1, rec->text2, rec->buf_length); - - rec->pushpin = ppin_by_UdId(rec->UdId); - - if (rec->pushpin != NULL) - { - if (verbose_flag > 5) - { - printf("Found probable pushpin match\n"); - printf("pushpin name is: %s\n", rec->pushpin->UdName); - printf("Pushpin short note is: %s\n", rec->pushpin->NoteShort); - //printf("Pushpin long note is: %s\n", rec->pushpin->NoteLong); - } - - gpx_write_jour_point(rec); - } - else - { - printf("*** Warning *** Ignoring route point '%s' without matching pushpin\n", - rec->text1); - printf("(yes, I should do someting more clever than this).\n"); - if (rec->UdId) - printf("There should have been a matching pushin because UdId=%d\n", rec->UdId); - } - fflush(stdout); - - if (verbose_flag > 4) - { - printf("Dumping the recognised Journey waypoint record\n"); - printbuf(rec->buf, rec->buf_length); - } - return rec; -} - -void process_journey_stream (char* jour_file_name) -{ - int journey_num_pts; - int j; - int readbyte; - static int verify_eof_flag = 0; - char* jour_file_header = (char*)xmalloc(JOUR_FILE_HEAD_LEN); - char* jour_file_trailer; - int max_read_more = 10000; - int readmore=0; - int status; - char readmorebuf[10000]; - struct jourwpt_rec * rec; - - gpx_write_jour_header(); - - printf("Processing Journey stream\n"); - fflush(stdout); - fflush(gpx_file); - - - if ((jour_file = fopen(jour_file_name, "rb")) == NULL) - { - fprintf(stderr, "Quitting because I cannot open %s\n", jour_file_name); - exit(1); - } - - status = readbytes(jour_file, jour_file_header, JOUR_FILE_HEAD_LEN); - if (status!=JOUR_FILE_HEAD_LEN) - { - printf("Unexpected EOF in the Journey stream\n"); - gpx_write_jour_trailer(); - return; - } - - journey_num_pts = *(int*)(jour_file_header+JOUR_FILEOS_NUMREC); - printf("got Journey file header with %d waypoints\n", journey_num_pts); - if (verbose_flag > 4) - { - printbuf(jour_file_header, JOUR_FILE_HEAD_LEN); - } - - for (j=0; j< journey_num_pts; j++) - { - rec = read_journey_rec(j); - if (rec==NULL) - { - printf("Closing stream and skipping rest of Journey stream processing because I read a bad record\n"); - fclose(jour_file); - printf("Writing gpx route for Journey\n"); - fflush(stdout); - - gpx_write_jour_trailer(); - - printf("Finnished closing Journey stream after error.\n"); - return; - } - } - - jour_file_trailer = (char*)xmalloc(JOUR_FILE_TAIL_LEN); - - status = readbytes(jour_file, jour_file_trailer, JOUR_FILE_TAIL_LEN); - if (status!=JOUR_FILE_TAIL_LEN) - { - printf("Unexpected EOF while reading journey stream trailer\n"); - } - - if (verbose_flag > 4) - { - printf("got Journey file trailer\n"); - printbuf(jour_file_trailer, JOUR_FILE_TAIL_LEN); - } - - if ((readbyte = getc(jour_file))!=EOF) - { - fprintf (stderr, "Did not finish reading journey file at EOF\n"); - - do { - readmorebuf[readmore]=(char)readbyte; - readmore++; - if (readmore>max_read_more) - break; - } while ((readbyte = getc(jour_file))!=EOF); - - printf("read a further %d bytes past expected eof\n",readmore); - printbuf(readmorebuf, readmore); - } - - fclose(jour_file); - printf("Writing gpx route for Journey\n"); - fflush(stdout); - - gpx_write_jour_trailer(); - - printf("Finnished proccessing Journey stream.\n"); - fflush(stdout); - fflush(gpx_file); -} - -void read_ppin_list_csv(char* ppin_file_name) -// for reading my old style csv temp file for ppins -{ - int pinnum; - int params_read; - char ppin_line[500+MAX_PPIN_MEMO]; - char ppin_line_strings[500+MAX_PPIN_MEMO]; - struct pushpin * ppin; - char* status; - int UdNameLen=0; - int NoteShortLen=0; - int NoteLongLen=0; - - printf("Annalysing the pushpin temp file\n"); - - for (pinnum=0; pinnum < MAX_PUSHPINS; pinnum++) - ppin_list[pinnum] = NULL; - - if ((ppin_file = fopen(ppin_file_name, "r")) == NULL) - { - fprintf(stderr, "Cannot open %s\n", ppin_file_name); - exit(1); - } - - pinnum=0; - while (!feof( ppin_file)) - { - //printf("Reading pushpin %d\n", pinnum); - //fflush(stdout); - - ppin = (struct pushpin *)xmalloc(sizeof(struct pushpin)); - - status=fgets(ppin_line, 500+MAX_PPIN_MEMO, ppin_file); - - if (status==NULL) - { - printf("oops, trying to read empty line\n", pinnum); - break; - - } - else - { - //printf("Read ppin temp line: %s\n", ppin_line); - //fflush(stdout); - - params_read = sscanf(ppin_line, "%ld, %ld, %ld, %d, %d, %d, %[^\n]", - &(ppin->UdId), &(ppin->Grid), &(ppin->Precision), - &UdNameLen, &NoteShortLen, &NoteLongLen, ppin_line_strings); - - printf("Got pushpin UdId %ld Grid %d Precision %d ppin_line_strings %s\n", - ppin->UdId, ppin->Grid, ppin->Precision, ppin_line_strings); - fflush(stdout); - - if (params_read == 7) - { - ppin->UdName = (char*)xmalloc(UdNameLen+1); - memcpy(ppin->UdName, ppin_line_strings, UdNameLen); - ppin->UdName[UdNameLen]=0; - - ppin->NoteShort = (char*)xmalloc(NoteShortLen+1); - memcpy(ppin->NoteShort, ppin_line_strings+UdNameLen, NoteShortLen); - ppin->NoteShort[NoteShortLen]=0; - -// ppin->NoteLong = (char*)xmalloc(NoteLongLen+1); -// memcpy(ppin->NoteLong, ppin_line_strings+UdNameLen+NoteShortLen, NoteLongLen); -// ppin->NoteLong[NoteLongLen]=0; - - //printf("Read %d parameters ok\n", params_read); - //fflush(stdout); - - - ppin_list[pinnum]=ppin; - // printf("saving pushpin_linst[%d]: UdId %ld lat %g lon %g UdName %s\n", - // pinnum, ppin->UdId, ppin->lat, ppin->lon, ppin->UdName); - // fflush(stdout); - pinnum++; - } - else - { - printf("freeing this ppin (was# %d) because it did not read properly\n", - pinnum); - free(ppin); - break; - } - } - } - - fclose(ppin_file); - printf("Read %d pushpins, now writing to gpx\n", pinnum); - -} - -int check_file_empty(char* filename) -{ - int readchar; - FILE* file=fopen(filename, "rb"); - // also check if the file exists - if (file==NULL) - return 1; - readchar = fgetc(file); - if (readchar == EOF) - return 1; - else - return 0; -} - -void process_pushpin_file(char* ppin_file_name) -{ - int i=0; - struct point p; - struct ms_point msp; - - // dont try and open a empty mdb file - if (check_file_empty(ppin_file_name)) - return; - - read_ppin_list(ppin_file_name); - //read_ppin_list_csv(ppin_file_name); - - // set lat & lon for all pushpins - while(ppin_list[i] && (iGrid; - msp.precision = ppin_list[i]->Precision; - p = ms2latlong(msp); - - ppin_list[i]->lat = p.lat; - ppin_list[i]->lon = p.lon; - - if (verbose_flag > 3) - printf("Decoded pushpin %d lat %f, lon %f, UdName %s, NoteShort %s\n", - ppin_list[i]->UdId, ppin_list[i]->lat, ppin_list[i]->lon, - ppin_list[i]->UdName, ppin_list[i]->NoteShort); - - i++; - } - - gpx_write_pushpinlist(); - - printf("Finished reading pushpins\n"); - fflush(stdout); - fflush(gpx_file); -} - void show_usage() { printf("st2gpx - Export data from MS Streets & Trips and Autoroute to GPX format\n\n"); + // FIXME update this line printf("Usage: st2gpx [-hre] [-v verbose-level] [-a annotations-file] [-u userdata-file] "); printf("[-j journey-file] [-G gpx-file] stfile\n\n"); printf("-h : Help (this text)\n"); printf("-r : Export drawn-lines as routes instead of tracks\n"); - printf("-e : Explore data furhter\n"); + printf("-g gpx-in-file : Import data from GPX XML format gpx-in-file\n"); + printf("-G gpx-out-file : Write output to GPX XML format gpx-out-file\n"); + printf("-F st-mod-file : Write modified stfile with imported data\n"); + printf(" to (new) st-mod-file.\n"); + printf("-m mpst-in-file : Import data from Garmin MapSource text-export mpst-in-file\n"); + printf("-M pcx5-out-file : Write output to Garmin MapSource importable pcx5-out-file\n"); + printf("\n"); + printf("export hint:\t st2gpx stfile (or use drag & drop)\n"); + printf("import hint:\t st2gpx -g gpx-in-file -F st-mod-file st-template-file\n"); +// printf("\n"); + debug_pause(); + printf("Debugging options:\n"); + printf("-e : Explore data further\n"); printf("-v [n] : Set debugging verbosity to 'n' (0-6, default 2)\n"); printf("-u userdata-file : Process pushpins in (mdb) file userdata-file\n"); printf("-j journey-file : Process Journey in file journey-file\n"); printf("-a annotations-file : Process Annotations in file annotations-file\n"); - printf("-G gpx-file : Write output to gpx-file\n"); + printf("-p properties-file : Analyse OLE properties-file\n"); + + debug_pause(); exit(0); } void xsystem(char* syscmd) -// this is not ANSI { int status; printf("%s \n", syscmd); @@ -1308,38 +226,81 @@ void xsystem(char* syscmd) main(int argc, char** argv) { int c; - static int verify_eof_flag = 0; - char* jour_file_name=NULL; - char* annot_file_name=NULL; - char* ppin_file_name=NULL; - char* gpx_file_name=NULL; + + char* jour_in_file_name=NULL; + char* annot_in_file_name=NULL; + char* ppin_in_file_name=NULL; + char* gpx_in_file_name=NULL; + char* gpx_out_file_name=NULL; + char* import_file_name=NULL; + char* properties_file_name=NULL; + + char* contents_dir_name=NULL; + char source_full_path[_MAX_PATH]; + char contents_full_path[_MAX_PATH]; + + char* mpst_in_file_name=NULL; + char* pcx5_out_file_name=NULL; char syscmd[1000]; char cmddrv[_MAX_DRIVE]; char cmddir[_MAX_DIR]; char cmdfilename[_MAX_PATH]; char cmdext[_MAX_EXT]; - char cmdpath[_MAX_PATH]; + char * cmdpath=NULL; + + + struct pushpin_safelist* ppplist=NULL; + struct journey* jour=NULL; + struct annotations* annots=NULL; + struct gpx_data* all_gpx=NULL; + struct ole_property_set * strips_properties=NULL; + struct ole_property * prop = NULL; + struct contents * conts; + + char* temp_str=NULL; + +// int verify_eof_flag = 0; + + opts.explore_flag=0; + opts.use_gpx_route=0; + opts.verbose_flag=2; + opts.source_file_name=NULL; + opts.debug_wait_flag=0; + opts.st_version_num = 0; + opts.MapName = NULL; + + +#ifdef MEMCHK + // Call _CrtCheckMemory at every allocation and deallocation request. + SET_CRT_DEBUG_FIELD(_CRTDBG_CHECK_ALWAYS_DF); + // Keep freed memory blocks in the heaps linked list, assign them the _FREE_BLOCK type, + // and fill them with the byte value 0xDD. + SET_CRT_DEBUG_FIELD(_CRTDBG_DELAY_FREE_MEM_DF); + // Perform automatic leak checking at program exit via a call to _CrtDumpMemoryLeaks + // and generate an error report if the application failed to free all the memory + // it allocated. + SET_CRT_DEBUG_FIELD(_CRTDBG_LEAK_CHECK_DF); +#endif + +#ifdef DEBUG_STDOUT + _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT ); + _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT ); + _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT ); +#endif + + // _CrtSetBreakAlloc(136); - int debug_wait_flag=0; while (1) { - static struct option long_options[] = - { - {"file", required_argument, 0, 'f'}, - {"outfile", required_argument, 0, 'F'}, - {"verbose", optional_argument, 0, 'v'}, - {"explore", no_argument, &explore_flag, 1}, - {"route", no_argument, &use_gpx_route, 1}, - {0, 0, 0, 0} // what is this for? - }; /* getopt_long stores the option index here. */ int option_index = 0; - // c = getopt_long (argc, argv, "v::bqderf:F:", - // long_options, &option_index); - c = getopt(argc, argv, "hu:j:a:G:rv::ew"); + c = getopt(argc, argv, "hu:j:a:g:G:m:M:F:p:rv::ew"); /* Detect the end of the options. */ if (c == -1) @@ -1357,54 +318,89 @@ main(int argc, char** argv) case 'u': // read a UserData (pushpin) file directly - free(ppin_file_name); - ppin_file_name = (char*)xmalloc(strlen(optarg)+1); - strcpy(ppin_file_name, optarg); - if (verbose_flag > 1) - printf("Analysing UserData (pushpin) stream in file %s\n\n", jour_file_name); + free(ppin_in_file_name); + ppin_in_file_name = (char*)xmalloc(strlen(optarg)+1); + strcpy(ppin_in_file_name, optarg); + if (opts.verbose_flag > 1) + printf("Analysing UserData (pushpin) stream in file %s\n\n", jour_in_file_name); break; case 'j': // read a Journey file directly - free(jour_file_name); - jour_file_name = (char*)xmalloc(strlen(optarg)+1); - strcpy(jour_file_name, optarg); - if (verbose_flag > 1) - printf("Analysing Journey stream in file %s\n\n", jour_file_name); + free(jour_in_file_name); + jour_in_file_name = (char*)xmalloc(strlen(optarg)+1); + strcpy(jour_in_file_name, optarg); + if (opts.verbose_flag > 1) + printf("Analysing Journey stream in file %s\n\n", jour_in_file_name); break; case 'a': // read an annotation file directly - annot_file_name = (char*)xmalloc(strlen(optarg)+1); - strcpy(annot_file_name, optarg); - if (verbose_flag > 1) - printf("Analysing Annotation stream in file %s\n\n", annot_file_name); + annot_in_file_name = (char*)xmalloc(strlen(optarg)+1); + strcpy(annot_in_file_name, optarg); + if (opts.verbose_flag > 1) + printf("Analysing Annotation stream in file %s\n\n", annot_in_file_name); + break; + + case 'g': + gpx_in_file_name = (char*)xmalloc(strlen(optarg)+1); + strcpy(gpx_in_file_name, optarg); + if (opts.verbose_flag > 1) + printf("Reading GPX from file %s\n\n", gpx_in_file_name); break; case 'G': - gpx_file_name = (char*)xmalloc(200); - strcpy(gpx_file_name, optarg); - if (verbose_flag > 1) - printf("Writing GPX output to file %s\n\n", gpx_file_name); + gpx_out_file_name = (char*)xmalloc(strlen(optarg)+1); + strcpy(gpx_out_file_name, optarg); + if (opts.verbose_flag > 1) + printf("Writing GPX output to file %s\n\n", gpx_out_file_name); + break; + + case 'm': + mpst_in_file_name = (char*)xmalloc(strlen(optarg)+1); + strcpy(mpst_in_file_name, optarg); + if (opts.verbose_flag > 1) + printf("Reading Garmin MapSource Text format from file %s\n\n", mpst_in_file_name); + break; + + case 'M': + pcx5_out_file_name = (char*)xmalloc(strlen(optarg)+1); + strcpy(pcx5_out_file_name, optarg); + if (opts.verbose_flag > 1) + printf("Writing Garmin MapSource importable pcx5 output to file %s\n\n", pcx5_out_file_name); + break; + + case 'F': + import_file_name = (char*)xmalloc(strlen(optarg)+1); + strcpy(import_file_name, optarg); + if (opts.verbose_flag > 1) + printf("Writing modified s&t file with imported gpx data to file %s\n\n", import_file_name); + break; + + case 'p': + properties_file_name = (char*)xmalloc(strlen(optarg)+1); + strcpy(properties_file_name, optarg); + if (opts.verbose_flag > 1) + printf("Analysing OLE Properties from file %s\n\n", properties_file_name); break; case 'r': - use_gpx_route=1; + opts.use_gpx_route=1; break; case 'v': if (optarg==NULL) - verbose_flag=5; + opts.verbose_flag=5; else - verbose_flag = atoi(optarg); + opts.verbose_flag = atoi(optarg); break; case 'e': - explore_flag = 1; + opts.explore_flag = 1; break; case 'w': - debug_wait_flag = 1; + opts.debug_wait_flag = 1; break; case '?': @@ -1420,44 +416,32 @@ main(int argc, char** argv) if (optind == argc-1) { - source_file_name = (char*)xmalloc(strlen(argv[optind])+1); - strcpy(source_file_name, argv[optind]); - if (verbose_flag > 1) - printf("Analysing autoroute file %s\n\n", source_file_name); - if (ppin_file_name==NULL) - { - ppin_file_name = (char*)xmalloc(strlen(source_file_name)+30); - sprintf(ppin_file_name, "%s.Contents\\UserData.mdb", source_file_name); - } - if (jour_file_name==NULL) - { - jour_file_name = (char*)xmalloc(strlen(source_file_name)+30); - sprintf(jour_file_name, "%s.Contents\\Journey", source_file_name); - } - if (annot_file_name==NULL) - { - annot_file_name = (char*)xmalloc(strlen(source_file_name)+30); - sprintf(annot_file_name, "%s.Contents\\Annotations", source_file_name); - } - if (gpx_file_name==NULL) - { - gpx_file_name = (char*)xmalloc(strlen(source_file_name)+30); - // should remove the est or axe suffix - sprintf(gpx_file_name, "%s.gpx", source_file_name); - } + opts.source_file_name = (char*)xmalloc(strlen(argv[optind])+1); + strcpy(opts.source_file_name, argv[optind]); + if (opts.verbose_flag > 1) + printf("Analysing autoroute file %s\n\n", opts.source_file_name); + if (ppin_in_file_name==NULL) + ppin_in_file_name = strappend(opts.source_file_name, ".Contents\\UserData.mdb"); + if (jour_in_file_name==NULL) + jour_in_file_name = strappend(opts.source_file_name, ".Contents\\Journey"); + if (annot_in_file_name==NULL) + annot_in_file_name = strappend(opts.source_file_name, ".Contents\\Annotations"); + if ((gpx_out_file_name==NULL) && (gpx_in_file_name==NULL)) + gpx_out_file_name = strappend(opts.source_file_name, ".gpx"); } else if (optind < argc-1) { printf("Unrecognised option %s\n", argv[optind+1]); show_usage(); - } + + } else { - if (verbose_flag > 1) + if (opts.verbose_flag > 1) printf("Not analysing any core S&T or autoroute file\n"); } - if (source_file_name) + if (opts.source_file_name) { // Open the compound file using the istorage utility // I probably should do this in a library and use streams instead of files @@ -1466,58 +450,192 @@ main(int argc, char** argv) // this is not ANSI _splitpath(argv[0], cmddrv, cmddir, cmdfilename, cmdext); - sprintf(cmdpath, "%s%s", cmddrv, cmddir); + //sprintf(cmdpath, "%s%s", cmddrv, cmddir); + cmdpath = strappend(cmddrv, cmddir); - sprintf(syscmd, "%sistorage\\istorage.exe %s", cmdpath, source_file_name); - xsystem(syscmd); + _fullpath(source_full_path, opts.source_file_name, _MAX_PATH); - // clean up previous copy of this. It should already have been deleted... - sprintf(syscmd, "del %s.Contents\\UserData.mdb", source_file_name); + sprintf(syscmd, "%sistorage\\istorage.exe \"%s\"", cmdpath, source_full_path); xsystem(syscmd); - sprintf(syscmd, "rename %s.Contents\\UserData. UserData.mdb", source_file_name); + printf("*****************************************************************\n"); + printf("Finished istorage command\n"); + + sprintf(syscmd, "rename \"%s.Contents\\UserData.\" UserData.mdb", opts.source_file_name); xsystem(syscmd); } + // *************************** // begin processing the files - gpx_open_write_file_header(gpx_file_name); + // *************************** - if (ppin_file_name) - process_pushpin_file(ppin_file_name); - if (jour_file_name) - process_journey_stream(jour_file_name); - if (annot_file_name) - process_annotations_stream(annot_file_name); + // Read GPX import file + if (gpx_in_file_name) + { + all_gpx = process_gpx_in_file(gpx_in_file_name); + if (all_gpx==NULL) + printf("Didn't read any usable data from %s ???\n",gpx_in_file_name); + printf("Read %d waypoints, %d routes and %d tracks from file %s\n", all_gpx->wpt_list_count, all_gpx->rte_list_count, all_gpx->trk_list_count, gpx_in_file_name); + printf("Importing this data as %d lines\n", all_gpx->rte_list_count + all_gpx->trk_list_count); + } - gpx_write_file_trailer(); + // Read Mapsource text-export file. + // Does it make any sense to try and merge with all_gpx from above? Not for now... + if (mpst_in_file_name) + { + gpx_data_delete(all_gpx); + all_gpx = read_mpstext(mpst_in_file_name); + if (all_gpx==NULL) + printf("Didn't read any usable data from %s ???\n",mpst_in_file_name); + printf("Read %d waypoints, %d routes and %d tracks from file %s\n", + all_gpx->wpt_list_count, all_gpx->rte_list_count, + all_gpx->trk_list_count, mpst_in_file_name); + printf("Importing this data as %d lines\n", + all_gpx->rte_list_count + all_gpx->trk_list_count); + } + // ole properties from S&T source file + if (opts.source_file_name) + { + strips_properties=read_ole_properties(opts.source_file_name, NULL); + prop = get_propterty(strips_properties, 0x60002); + if ((prop!=NULL) && (prop->buf != NULL) ) + { + opts.st_version_num = *(int*)(prop->buf); + printf("Autoroute/S&T version in %s is %d\n", opts.source_file_name, opts.st_version_num); + } + prop = get_propterty(strips_properties, 0x10000); + if ((prop!=NULL) && (prop->buf != NULL) ) + { + opts.MapName = (WCHAR*)(prop->buf + 4); + wprintf(L"MapName is %ls\n", opts.MapName); + if(wcscmp(opts.MapName, L"USA")==0) + opts.isUSA=1; + else if(wcscmp(opts.MapName, L"EUR")!=0 ) + printf("Unknown map type, assuming EUR\n"); + } + } - // Clean up the compound file directory - if (source_file_name) + // check the contents stream + //if(opts.explore_flag) { - sprintf(syscmd, "echo y|del %s.Contents", source_file_name); - xsystem(syscmd); + temp_str = strappend(opts.source_file_name, ".Contents\\Contents"); + conts = read_contents(temp_str); + free(temp_str); + temp_str=NULL; + } + + // ole properties from any file, just for debuging + if (properties_file_name) + ole_property_set_delete(read_ole_properties(NULL,opts.source_file_name)); + + // read the data in the S&T source file + if (ppin_in_file_name) + ppplist = process_pushpin_file(ppin_in_file_name); + if (jour_in_file_name) + jour = process_journey_stream(jour_in_file_name, ppplist); + if (annot_in_file_name) + annots = process_annotations_stream(annot_in_file_name); + + // export GPX + if ( (gpx_out_file_name) && (all_gpx==NULL) ) + gpx_write_all(gpx_out_file_name, ppplist, jour, annots); - // just for debuging - if (debug_wait_flag) + // export Mapsource pcx5 + if (pcx5_out_file_name) + pcx5_export(pcx5_out_file_name, ppplist, jour, annots); + + // Merge the data in the S&T source file with any imported GPX/mapsource data + if ((all_gpx!=NULL) && (opts.source_file_name!=NULL)) { - fprintf(stderr, "kill that ado connection!\n"); - fprintf(stderr, "Hit any key to continue\n"); - getchar(); + merge_gpx_annot(annots, all_gpx); + if (annots==NULL) + printf("After merging data, dont have any annotations???\n"); + printf("After merging data, there are %d annotations\n", annots->num_annotations); + //print_annotations(annots); + write_annotations(annots, annot_in_file_name); + //print_annotations(annots); + + // ******************** + // This is experimantal + // ******************** + temp_str = strappend(opts.source_file_name, ".Contents\\Contents"); + write_pushpins_from_gpx(ppin_in_file_name, all_gpx, conts, temp_str); + free(temp_str); + temp_str=NULL; } - // how do I do this? - sprintf(syscmd, "del %s.Contents\\UserData.mdb", source_file_name); + // create the s&t/autoroute file from the modified parts + if ((opts.source_file_name!=NULL) && (all_gpx!=NULL) && (import_file_name!=NULL)) + { + // Actually, we should allow NULL import_file_name and invent a sensible name + + sprintf(syscmd, "rename %s.Contents\\UserData.mdb UserData.", opts.source_file_name); xsystem(syscmd); - sprintf(syscmd, "rmdir %s.Contents", source_file_name); + contents_dir_name=(char*)xmalloc(strlen(opts.source_file_name)+20); + sprintf(contents_dir_name, "%s.Contents", opts.source_file_name); + + _fullpath(contents_full_path, contents_dir_name, _MAX_PATH); + + sprintf(syscmd, "%sistorage\\istorage-make.exe \"%s\"", cmdpath, contents_full_path); xsystem(syscmd); + + printf("*****************************************************************\n"); + printf("Finished istorage-make command\n"); + + sprintf(syscmd, "del \"%s\"", import_file_name); + xsystem(syscmd); + + _splitpath(opts.source_file_name, cmddrv, cmddir, cmdfilename, cmdext); + sprintf(syscmd, "move \"%s.Contents.ole\" \"%s\"", opts.source_file_name, import_file_name); + xsystem(syscmd); + } - // just for debuging - if (debug_wait_flag) + // Clean up the compound file directory + if (opts.source_file_name) { - fprintf(stderr, "Hit any key to continue\n"); - getchar(); + { + sprintf(syscmd, "echo y|del \"%s.Contents\"", opts.source_file_name); + xsystem(syscmd); + + sprintf(syscmd, "rmdir \"%s.Contents\"", opts.source_file_name); + xsystem(syscmd); + } } + + // free variables. Not really necessary. + annotations_delete(annots); + pushpin_safelist_delete(ppplist); + journey_delete(jour); + gpx_data_delete(all_gpx); + ole_property_set_delete(strips_properties); + contents_delete(conts); + + xfree(cmdpath); + xfree(ppin_in_file_name); + xfree(jour_in_file_name); + xfree(annot_in_file_name); + xfree(gpx_in_file_name); + xfree(gpx_out_file_name); + xfree(pcx5_out_file_name); + xfree(import_file_name); + xfree(opts.source_file_name); + xfree(contents_dir_name); + xfree(mpst_in_file_name); + + if (opts.verbose_flag>5) + printf("Done freeing all\n"); + + //debug_show_sizes(); + //debug_pause(); + //printf("exiting main\n"); + + _flushall(); + +#ifdef _DEBUG +// _CrtDumpMemoryLeaks(); +#endif + debug_pause(); } diff --git a/st2gpx/src/st2gpx.dsp b/st2gpx/src/st2gpx.dsp index 14589899a..1d369b1a6 100644 --- a/st2gpx/src/st2gpx.dsp +++ b/st2gpx/src/st2gpx.dsp @@ -39,9 +39,10 @@ RSC=rc.exe # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /Zp1 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -49,7 +50,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 libexpat.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 !ELSEIF "$(CFG)" == "st2gpx - Win32 Debug" @@ -62,9 +63,10 @@ LINK32=link.exe # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c +# ADD CPP /nologo /Zp1 /Za /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe @@ -72,7 +74,8 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libexpat.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# SUBTRACT LINK32 /profile /map !ENDIF @@ -85,7 +88,53 @@ LINK32=link.exe # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File +SOURCE=.\annotations.c +# End Source File +# Begin Source File + +SOURCE=.\contents.c +# End Source File +# Begin Source File + +SOURCE=.\debug.c +# End Source File +# Begin Source File + SOURCE=.\getopt.c + +!IF "$(CFG)" == "st2gpx - Win32 Release" + +!ELSEIF "$(CFG)" == "st2gpx - Win32 Debug" + +# ADD CPP /Ze + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\journey.c +# End Source File +# Begin Source File + +SOURCE=.\nannol.c +# End Source File +# Begin Source File + +SOURCE=.\ppinutil.c +# End Source File +# Begin Source File + +SOURCE=.\properties.c + +!IF "$(CFG)" == "st2gpx - Win32 Release" + +!ELSEIF "$(CFG)" == "st2gpx - Win32 Debug" + +# ADD CPP /Ze + +!ENDIF + # End Source File # Begin Source File @@ -95,13 +144,21 @@ SOURCE=.\pushpins.cpp !ELSEIF "$(CFG)" == "st2gpx - Win32 Debug" -# ADD CPP /W4 +# ADD CPP /Ze /W4 /Gi !ENDIF # End Source File # Begin Source File +SOURCE=.\readgpx.c +# End Source File +# Begin Source File + +SOURCE=.\readmpst.c +# End Source File +# Begin Source File + SOURCE=.\st2gpx.c !IF "$(CFG)" == "st2gpx - Win32 Release" @@ -112,6 +169,14 @@ SOURCE=.\st2gpx.c !ENDIF +# End Source File +# Begin Source File + +SOURCE=.\writegpx.c +# End Source File +# Begin Source File + +SOURCE=.\writepcx.c # End Source File # End Group # Begin Group "Header Files" @@ -119,16 +184,60 @@ SOURCE=.\st2gpx.c # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File +SOURCE=.\annotations.h +# End Source File +# Begin Source File + +SOURCE=.\contents.h +# End Source File +# Begin Source File + SOURCE=.\getopt.h # End Source File # Begin Source File +SOURCE=.\gpx.h +# End Source File +# Begin Source File + +SOURCE=.\journey.h +# End Source File +# Begin Source File + +SOURCE=.\ppinutil.h +# End Source File +# Begin Source File + +SOURCE=.\properties.h +# End Source File +# Begin Source File + SOURCE=.\pushpins.h # End Source File +# Begin Source File + +SOURCE=.\st2gpx.h +# End Source File # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group +# Begin Source File + +SOURCE=.\bugs.txt +# End Source File +# Begin Source File + +SOURCE=.\build.txt +# End Source File +# Begin Source File + +SOURCE=.\history.txt +# End Source File +# Begin Source File + +SOURCE=.\ToDo.txt +# End Source File # End Target # End Project diff --git a/st2gpx/src/st2gpx.dsw b/st2gpx/src/st2gpx.dsw index 19486fe9c..c71a2e211 100644 --- a/st2gpx/src/st2gpx.dsw +++ b/st2gpx/src/st2gpx.dsw @@ -3,18 +3,6 @@ Microsoft Developer Studio Workspace File, Format Version 6.00 ############################################################################### -Project: "VCADO"="..\..\..\sw\5191\Rosetta\CPP\#Import-upg\Vcado.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - Project: "st2gpx"=.\st2gpx.dsp - Package Owner=<4> Package=<5> diff --git a/st2gpx/src/st2gpx.h b/st2gpx/src/st2gpx.h new file mode 100644 index 000000000..667b1a38a --- /dev/null +++ b/st2gpx/src/st2gpx.h @@ -0,0 +1,142 @@ +/* + st2gpx.h + + Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format. + + Copyright (C) 2003 James Sherring, james_sherring@yahoo.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + + This app depends on istorage & istorage-make from Pabs (pabs3@zip.to) + and James Clark's Expat xml parser from http://www.libexpat.org/. + +*/ +#ifdef __cplusplus +extern "C" { +#endif + +#define MEMCHK +#define DEBUG_STDOUT +//#define MEMTRACE + +#ifdef _DEBUG +#define _CRTDBG_MAP_ALLOC +#define SET_CRT_DEBUG_FIELD(a) _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)) +#define CLEAR_CRT_DEBUG_FIELD(a) _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)) +#else +#define SET_CRT_DEBUG_FIELD(a) ((void) 0) +#define CLEAR_CRT_DEBUG_FIELD(a) ((void) 0) +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +typedef unsigned short WCHAR; + +//#define ST_VERSION_AUTOROUTE2001 1 +//#define ST_VERSION_STREETSTRIPS2000 2 +//#define ST_VERSION_STREETSTRIPS2001 3 + +//#define ST_VERSION_AUTOROUTE2002 4 +//#define ST_VERSION_AUTOROUTE2003 5 +//#define ST_VERSION_STREETSTRIPS2002 6 +//#define ST_VERSION_STREETSTRIPS2003 7 + +typedef struct st2gpx_options +{ + // 0 - only errors + // 1 also the structured data output, e.g. line point info + // 2 also record types & parameters + // 3 also detailed summary info + // 4 also detailed analysis of headers & record params + // 5 also dump buffers + // 6 lots of debug info + int verbose_flag; + int explore_flag; + // force line-type annotations to be exported as GPX routes instead of tracks + int use_gpx_route; + char* source_file_name; + // wait for enter key at certain points in the program + int debug_wait_flag; + int st_version_num; + WCHAR* MapName; + // 0 for EUR, i.e. Autoroute + // 1 for USA, i,e, Streets & Trips + unsigned char isUSA; +} tag_st2gpx_options; + + +// FIXME is this the correct way to forward define these? +#ifndef __cplusplus + +extern struct point; +extern struct pushpin; +extern struct annotations; +extern struct pushpin_safelist; +extern struct annot_rec ; +extern struct gpx_data; +extern struct f_jour_pt_head; +extern struct f_jour_pt_tail; +extern struct f_jour_opts_EUR_8; +extern struct f_jour_opts_EUR_10; +extern struct f_jour_opts_USA_8; +extern struct f_jour_opts_USA_10; +extern struct f_jour_opts; +extern struct f_jour_avoid; +extern struct f_jour_trailer; +extern struct journey; +extern struct f_jour_header; +extern struct contents; + +#endif // __cplusplus + +//st2gpx.c +extern struct st2gpx_options opts; +void * xmalloc(size_t size); +void * xrealloc(void* ptr, size_t size); +void xfree(void * obj); +char * str2ascii(char* str); +int readbytes(FILE* file, char* buf, int bytes2read); +//nannol.c +struct annotations * merge_gpx_annot(struct annotations * annots, struct gpx_data* all_gpx); +void write_annotations(struct annotations * annots, char* annot_out_file_name); +//writepcx.c +void pcx5_export(char* pcx5_out_file_name, struct pushpin_safelist * ppplist, struct journey * jour, struct annotations * pannots); +//debug.c +void debug_pause(); +void printbuf(char* buf, int len); +void explore_annot(struct annot_rec * rec); +void print_f_jour_header(struct f_jour_header * head); +void print_f_jour_pt_head(struct f_jour_pt_head * pt_head); +void print_f_jour_pt_tail(struct f_jour_pt_tail * pt_tail); +void print_f_jour_opts(struct f_jour_opts * jopts); +void print_f_jour_opts_EUR_8(struct f_jour_opts_EUR_8 * jopts); +void print_f_jour_opts_EUR_10(struct f_jour_opts_EUR_10 * jopts); +void print_f_jour_opts_USA_8(struct f_jour_opts_USA_8 * jopts); +void print_f_jour_opts_USA_10(struct f_jour_opts_USA_10 * jopts); +void print_f_jour_avoid(struct f_jour_avoid * avoid); +void print_f_jour_trailer(struct f_jour_trailer * trailer); +void print_annot_rec(struct annot_rec * rec); +void print_annotations(struct annotations * annots); +void debug_show_sizes(); +//st2gpx.c +struct gpx_data * read_mpstext(char* mpstxt_file_name); + +#ifdef __cplusplus +} +#endif + diff --git a/st2gpx/src/writegpx.c b/st2gpx/src/writegpx.c new file mode 100644 index 000000000..34bbcdf23 --- /dev/null +++ b/st2gpx/src/writegpx.c @@ -0,0 +1,317 @@ +/* + writegpx.c + + Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format. + + Copyright (C) 2003 James Sherring, james_sherring@yahoo.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + + This app depends on istorage & istorage-make from Pabs (pabs3@zip.to) + and James Clark's Expat xml parser from http://www.libexpat.org/. + +*/ +#include +#include +#include + +#include "st2gpx.h" +#include "gpx.h" +#include "ppinutil.h" +#include "journey.h" +#include "annotations.h" + +#define GPX_HEADER1 "\n\n" +#define GPX_THIS_PROGRAM "st2gpx from james_sherring@yahoo.com" +#define GPX_FOOTER "" + +#define GPX_WPT 0 +#define GPX_RTEPT 1 +#define GPX_TRKPT 2 +char * gpxptypelabel[3] = {"wpt", "rtept", "trkpt"}; + +FILE* gpx_open_write_file_header(char* gpx_out_file_name) +{ + FILE* gpx_out_file=NULL; + + if (gpx_out_file_name) + { + gpx_out_file = fopen(gpx_out_file_name, "w"); + if (gpx_out_file == NULL) + { + fprintf(stderr, "Cannot open %s\n", gpx_out_file_name); + debug_pause(); + exit(1); + } + } + else + return NULL; + + if (gpx_out_file!=NULL) + { + fprintf(gpx_out_file, GPX_HEADER1); + fprintf(gpx_out_file, GPX_HEADER2); + if (opts.source_file_name) + fprintf(gpx_out_file, "\tThis file was created from %s by %s\n", + opts.source_file_name, GPX_THIS_PROGRAM); + // Some more tags we should add here + // Descriptive name of the GPX file + // Description of the GPX file + // Name of the file's creator + // \n\t\n"); + + case ANNOT_TYPE_OVAL: + case ANNOT_TYPE_TEXT: + case ANNOT_TYPE_CIRCLE: + default: + break; + } +} + +void gpx_write_annotations(FILE* gpx_out_file, struct annotations * annots) +{ + int i; + if ( (gpx_out_file!=NULL) && (annots!=NULL) ) + for (i=0; i < annots->num_annotations; i++) + { + gpx_write_annot_rec(gpx_out_file, annots->annot_list[i]); + } +} + +void gpx_write_all(char* gpx_out_file_name, + struct pushpin_safelist *ppplist, + struct journey * jour, + struct annotations * annots) +{ + FILE* gpx_out_file; + if ( (ppplist==NULL) && (jour==NULL) && (annots==NULL) ) + return; + gpx_out_file = gpx_open_write_file_header(gpx_out_file_name); + gpx_write_pushpinlist(gpx_out_file, ppplist); + gpx_write_journey(gpx_out_file, jour); + gpx_write_annotations(gpx_out_file, annots); + gpx_write_file_trailer(gpx_out_file); +} + diff --git a/st2gpx/src/writepcx.c b/st2gpx/src/writepcx.c new file mode 100644 index 000000000..16d293572 --- /dev/null +++ b/st2gpx/src/writepcx.c @@ -0,0 +1,469 @@ +/* + writepcx.c + + Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format. + + Copyright (C) 2003 James Sherring, james_sherring@yahoo.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + + This app depends on istorage & istorage-make from Pabs (pabs3@zip.to) + and James Clark's Expat xml parser from http://www.libexpat.org/. + +*/ +#include +#include +#include +#include +#include + +#include "gpx.h" +#include "st2gpx.h" +#include "ppinutil.h" +#include "journey.h" +#include "annotations.h" + +#define GAR_WPT_HEADER "H IDNT LATITUDE LONGITUDE DATE TIME ALT DESCRIPTION PROXIMITY SYMBOL ;waypts\n" +#define GAR_RTE_HEADER_JOUR "R 01 Streets&Trips Journey\n" +#define GAR_TRK_HEADER "H LATITUDE LONGITUDE DATE TIME ALT ;track\n" + +#define GAR_WPT 1 +#define GAR_RTE 2 +#define GAR_TRK 3 + +// maximum number of susbstitutions to try get a unique IDENT +#define MAX_IDENT_SUB 10000 + +char* strpad(char* str, int padlen) +// Right-pad a string with spaces so that strlen(str)=padlen, +// or just truncate str if it is longer that padlen. +// str must have at least padlen+1 bytes allocated. +{ + int i; + str[padlen]=0; + for(i=strlen(str); i96) && (c<123)) + c= str[i]=c-32; + //convert all non-conforming characters to spaces + if( !( ((c>47) && (c<59)) || ((c>64) && (c<91)) || (c==45) )) + { + str[i]=' '; + } + } + str[6]=0; +} + +void comp_mk_uniq_idents(char* ident_array, int ident_to_mk_uniq, int count_idents) +// compare ident_to_mk_uniq-th ident to all preceding idents, +// and make ident_to_mk_uniq-th ident +{ + int j; + int k; + int m; + char test_ident[7]; + char uniq_part[7]; + int duplicate_flag; + + // compare this ident with all the idents verified as unique + for(j=0; jcount_rtepts == 0) + return; + } + else + count_ppins=ppplist->num_pushpins; + + ident_array=(char*)xmalloc(7*(count_ppins + jour->count_rtepts)); + + // copy ppin names before we start mangling them + for (i=0; i< (count_ppins); i++) + { + if(ppplist->pushpin_list[i]->UdName) + memcpy(ident_array +7*i, ppplist->pushpin_list[i]->UdName, 6); + else + ident_array[7*i]=0; + //printf("pushpin_list[%d]->UdName:%s\n", i, ppplist->pushpin_list[i]->UdName); + //printf("ident_array[7*%d]:%s\n", i, ident_array+7*i); + garmin_ident_crush(ident_array+7*i); + //printf("Made Ident:%s\n",ident_array+7*i ); + } + + // copy rtept names before we start mangling them + for (i=0; i< (jour->count_rtepts); i++) + { + memcpy(ident_array + 7*(count_ppins) +7*i, + jour->rtept_list[i].text1, + 6); + garmin_ident_crush(ident_array + 7*(count_ppins) + 7*i); + } + + // compare all fresh ppin idents + for(i=0; i<(count_ppins); i++) + { + // Verify ident_array[7*i] is unique. + // Create a unique ident if neccesary. + // Only check against list of already-verified unique + comp_mk_uniq_idents(ident_array, i, count_ppins + jour->count_rtepts); + + strncpy(ppplist->pushpin_list[i]->garmin_ident, ident_array+7*i, 7); + } + + // compare jour rtept idents to ppin idents + other jour rtept idents + for(i=0; icount_rtepts; i++) + { + if (jour->rtept_list[i].pushpin != NULL) + { + // The rtept has a matching pushpin, so use the pushpin's garmin_ident + memcpy(jour->rtept_list[i].garmin_ident, + jour->rtept_list[i].pushpin->garmin_ident, + 7); + } + else + { + f_wpt_head = (struct f_jour_pt_head *)(jour->buf + (jour->rtept_list[i].pthead_os)); + lat=scaled2deg(f_wpt_head->scaled_lat); + lon=scaled2deg(f_wpt_head->scaled_lon); + for(j=0; jpushpin_list[j]->lat)<0.00001) + && (fabs(lon-ppplist->pushpin_list[j]->lon)<0.00001) ) + { + // The rtept has a matching pushpin, so use the pushpin's garmin_ident + memcpy(ident_array + 7*(count_ppins) +7*i, + ppplist->pushpin_list[j]->garmin_ident, + 7); + // Although the journey stream doesn't associate this pushpin with the route, + // I have decided to. Again, this is questionable + // but not likely to happen anyway. + jour->rtept_list[i].pushpin = ppplist->pushpin_list[j]; + } + else + { + // no matching wpt for this rtept, so we need to create one. + // We just create the garmin_ident in the jour-rtept here, + // later we will write a corresponding wpt to the pcx file. + comp_mk_uniq_idents(ident_array, count_ppins + i, count_ppins + jour->count_rtepts); + } + } + // set the jour-rtept garmin_ident + memcpy(jour->rtept_list[i].garmin_ident, + ident_array + 7*(count_ppins) +7*i, + 7); + } + xfree(ident_array); +} + +void gar_write_header(FILE* gar_out_file) +{ + fprintf(gar_out_file, "H SOFTWARE NAME & VERSION\n"); + fprintf(gar_out_file, "I PCX5 2.09 output from st2gpx by James Sherring - james_sherring@yahoo.com"); + fprintf(gar_out_file, "\n"); + fprintf(gar_out_file, "H R DATUM IDX DA DF DX DY DZ\n"); + fprintf(gar_out_file, "M G WGS 84 121 +0.000000e+00 +0.000000e+00 +0.000000e+00 +0.000000e+00 +0.000000e+00\n"); + fprintf(gar_out_file, "\n"); + fprintf(gar_out_file, "H COORDINATE SYSTEM\n"); + fprintf(gar_out_file, "U LAT LON DM\n"); + fprintf(gar_out_file, "\n"); +} + +void pcx5_write_pt(FILE* file, int pt_type, char ident[7], double lat, double lon, char timedate[19], + float alt, char desc[41], float proximity, int symbol) +{ + //char outbuf[118]; + char lat_sym; + char lon_sym; + int lat_deg; + int lon_deg; + double lat_min; + double lon_min; + + if (lat<0) + lat_sym='S'; + else + lat_sym='N'; + + if (lon<0) + lon_sym='W'; + else + lon_sym='E'; + + lat_deg=(int)floor(fabs(lat)); + lon_deg=(int)floor(fabs(lon)); + + lat_min=(fabs(lat)-lat_deg)*60; + lon_min=(fabs(lon)-lon_deg)*60; + + if ( (pt_type == GAR_WPT) || (pt_type == GAR_RTE) ) + fprintf(file, "W %6.6s ", ident); + else if (pt_type == GAR_TRK) + fprintf(file, "T "); + + fprintf(file, "%c%02.2d%08.5f %c%03.3d%08.5f", lat_sym, lat_deg, lat_min, lon_sym, lon_deg, lon_min); + fprintf(file, " %18.18s %5.5s", timedate, " "); + + if ( (pt_type == GAR_WPT) || (pt_type == GAR_RTE) ) + fprintf(file, " %40.40s %13.13s %1.3d \n", desc, " ", symbol); + else if (pt_type == GAR_TRK) + fprintf(file, "\n"); + +} + +void pcx5_write_ppin(FILE* file, struct pushpin * ppin) +{ + char timedate[19]=""; + float alt=0; + char desc[41]=""; + float proximity=0; + // FIXME this should come from the pushpin icon + int symbol=8; // or 18 + + strpad(timedate, 19); + + // Should I create a meaningful note if there is none? + if(ppin->NoteShort) + memcpy(desc, ppin->NoteShort, 40); + else + desc[0]=0; + strpad(desc, 40); + + pcx5_write_pt(file, GAR_WPT, ppin->garmin_ident, ppin->lat, ppin->lon, timedate, + alt, desc, proximity, symbol); +} + +void pcx5_write_ppin_list(FILE* file, struct pushpin_safelist * ppplist) +{ + int i; + + if ( (file==NULL) || (ppplist==NULL)) + return; + + fprintf(file, GAR_WPT_HEADER); + for (i=0; i< (ppplist->num_pushpins); i++) + pcx5_write_ppin(file, ppplist->pushpin_list[i]); +} + +void pcx5_write_jour_pt(FILE* file, struct journey * jour, struct jour_rtept * rtept, int pt_type) +{ + char timedate[19]=""; + float alt=0; + char desc[40]; + float proximity=0; + + int symbol=8; // or 18 + struct f_jour_pt_head * f_wpt_head; + +// if(pt_type==GAR_WPT) +// { + f_wpt_head = (struct f_jour_pt_head *)(jour->buf + (rtept->pthead_os)); + + strpad(timedate, 19); + + strcpy(desc, rtept->text1); + strpad(desc, 40); + + pcx5_write_pt(file, + pt_type, + rtept->garmin_ident, + scaled2deg(f_wpt_head->scaled_lat), + scaled2deg(f_wpt_head->scaled_lon), + timedate, + alt, + desc, + proximity, + symbol); +// } +// else if(pt_type==GAR_RTE) +// { +// // this is easier that calling pcx5_write_pt +// fprintf(file, "W %6.6s \n", rtept->garmin_ident); +// } +} + +void pcx5_write_journey(FILE* file, struct journey * jour, struct pushpin_safelist * ppplist) +{ + int i; + + if( (jour==NULL) || ((jour->count_rtepts) < 1) ) + return; + + // write jour rte-pts w/o ppin as wpts +// for(i=0; i< jour->count_rtepts; i++) +// if(jour->rtept_list[i].pushpin == NULL) +// pcx5_write_jour_pt(file, jour, jour->rtept_list + i, GAR_WPT); + + fprintf(file, "\n"); + fprintf(file, GAR_RTE_HEADER_JOUR); + fprintf(file, "\n"); + fprintf(file, GAR_WPT_HEADER); + + for(i=0; i< jour->count_rtepts; i++) + if(jour->rtept_list[i].pushpin) + pcx5_write_ppin(file, jour->rtept_list[i].pushpin); + else + pcx5_write_jour_pt(file, jour, jour->rtept_list+i, GAR_RTE); +} + +void pcx5_write_annot_line(FILE* file, struct annot_rec * pannot) +{ + int p; + char timedate[19]=""; + float alt=0; + struct gpxpt * pt; + + if (pannot==NULL) + return; + + fprintf(file, "\n"); + fprintf(file, GAR_TRK_HEADER); + + strpad(timedate, 19); + + for(p=0; pline_points; p++) + { + pt=gpx_get_point(pannot->buf + pannot->line_offset + 12*p); + if (pt != NULL) + pcx5_write_pt(file, GAR_TRK, "", pt->lat, pt->lon, timedate, + alt, "", 0, 0); + else + { + printf("Null gpx_pt #%p from annotation %d, skipping more points in this annotation\n", + pannot->annot_num); + break; + } + gpxpt_delete(pt); + } +} + +void pcx5_write_annots(FILE* file, struct annotations * pannots) +{ + int i; + if (pannots==NULL) + return; + + for(i=0; i < pannots->num_annotations; i++) + if ( (pannots->annot_list[i]->type) == ANNOT_TYPE_LINE) + pcx5_write_annot_line(file, pannots->annot_list[i]); + +} + +void pcx5_export(char* pcx5_out_file_name, struct pushpin_safelist * ppplist, struct journey * jour, struct annotations * pannots) +{ + FILE* pcx5_out_file=NULL; + struct pushpin_safelist * new_ppplist=NULL; + + if ( (ppplist==NULL) && (jour==NULL) && (pannots==NULL) ) + return; + + // Because Garmin can only accept a nasty 6 char alphanumeric unique ID + make_uniq_idents(ppplist, jour); + + if (pcx5_out_file_name) + { + pcx5_out_file = fopen(pcx5_out_file_name, "w"); + if (pcx5_out_file == NULL) + { + fprintf(stderr, "Cannot open %s\n", pcx5_out_file_name); + debug_pause(); + exit(1); + } + } + else + return; + + gar_write_header(pcx5_out_file); + pcx5_write_ppin_list(pcx5_out_file, ppplist); + pcx5_write_journey(pcx5_out_file, jour, ppplist); + pcx5_write_annots(pcx5_out_file, pannots); +}; -- 2.30.2